package org.openntf.domino.graph2.impl;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javolution.util.FastMap;
import javolution.util.FastSet;
import javolution.util.FastTable;
import org.openntf.domino.Database;
import org.openntf.domino.Document;
import org.openntf.domino.NoteCollection;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.big.NoteCoordinate;
import org.openntf.domino.big.ViewEntryCoordinate;
import org.openntf.domino.exceptions.UnimplementedException;
import org.openntf.domino.graph2.DIdentityFactory;
import org.openntf.domino.graph2.builtin.CategoryVertex;
import org.openntf.domino.graph2.builtin.ViewVertex;
import org.openntf.domino.utils.DominoUtils;
import org.openntf.domino.utils.Factory;
import com.google.common.base.Strings;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.VertexFrame;
public class DElementStore implements org.openntf.domino.graph2.DElementStore {
@SuppressWarnings("unused")
private static final Logger log_ = Logger.getLogger(DElementStore.class.getName());
private List<Class<?>> types_;
private Object delegate_;
private Long delegateKey_;
private Object provisionalDelegateKey_;
private Object proxyDelegate_;
private Long proxyDelegateKey_;
private Object provisionalProxyDelegateKey_;
private DIdentityFactory identityFactory_;
private CustomProxyResolver proxyResolver_;
private transient Map<Object, NoteCoordinate> keyCache_;
private transient Map<Object, Element> elementCache_;
private transient org.openntf.domino.graph2.DConfiguration configuration_;
protected void setTypes(final List<Class<?>> types) {
types_ = types;
}
protected Map<Object, Element> getElementCache() {
if (elementCache_ == null) {
elementCache_ = new FastMap<Object, Element>().atomic();
}
return elementCache_;
}
protected Map<Object, NoteCoordinate> getKeyCache() {
if (keyCache_ == null) {
keyCache_ = new FastMap<Object, NoteCoordinate>().atomic();
}
return keyCache_;
}
public DElementStore() {
addType(ViewVertex.class);
addType(CategoryVertex.class);
}
@Override
public void uncache(final Element elem) {
getElementCache().remove(elem);
}
@Override
public org.openntf.domino.graph2.DConfiguration getConfiguration() {
return configuration_;
}
public void setConfiguration(final DConfiguration config) {
configuration_ = config;
}
@Override
public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
delegateKey_ = in.readLong();
int count = in.readInt();
types_ = new FastTable<Class<?>>();
ClassLoader cl = Factory.getClassLoader();
if (cl == null)
cl = Thread.currentThread().getContextClassLoader();
for (int i = 0; i < count; i++) {
String className = in.readUTF();
Class<?> clazz = cl.loadClass(className);
types_.add(clazz);
}
}
@Override
public void writeExternal(final ObjectOutput out) throws IOException {
out.writeLong(delegateKey_);
out.writeInt(getTypes().size());
for (Class<?> clazz : getTypes()) {
out.writeUTF(clazz.getName());
}
}
@Override
public void addType(final Class<?> type) {
List<Class<?>> types = getTypes();
if (!types.contains(type)) {
types.add(type);
}
// for (Class<?> subtype : type.getClasses()) {
// if (subtype.isInterface()) {
// addType(subtype);
// }
// }
}
@Override
public void removeType(final Class<?> type) {
List<Class<?>> types = getTypes();
types.remove(type);
for (Class<?> subtype : type.getClasses()) {
removeType(subtype);
}
}
@Override
public List<Class<?>> getTypes() {
if (types_ == null) {
types_ = new FastTable<Class<?>>();
}
return types_;
}
@Override
public Object getStoreDelegate() {
if (delegate_ == null) {
org.openntf.domino.graph2.DConfiguration config = getConfiguration();
org.openntf.domino.graph2.DGraph graph = config.getGraph();
if (delegateKey_ == null) {
delegate_ = graph.getStoreDelegate(this, provisionalDelegateKey_);
} else {
delegate_ = graph.getStoreDelegate(this);
}
}
return delegate_;
}
@Override
public Object getProxyStoreDelegate() {
if (proxyDelegate_ == null) {
org.openntf.domino.graph2.DConfiguration config = getConfiguration();
org.openntf.domino.graph2.DGraph graph = config.getGraph();
if (proxyDelegateKey_ == null) {
proxyDelegate_ = graph.getProxyStoreDelegate(this, provisionalProxyDelegateKey_);
} else {
proxyDelegate_ = graph.getProxyStoreDelegate(this);
}
}
return proxyDelegate_;
}
@Override
public void setStoreDelegate(final Object store) {
delegate_ = store;
if (store instanceof Database) {
String rid = ((Database) store).getReplicaID();
delegateKey_ = NoteCoordinate.Utils.getLongFromReplid(rid);
} else {
//TODO Some other mechanism to get the key
}
}
@Override
public void setProxyStoreDelegate(final Object store) {
proxyDelegate_ = store;
if (store instanceof Database) {
String rid = ((Database) store).getReplicaID();
proxyDelegateKey_ = NoteCoordinate.Utils.getLongFromReplid(rid);
} else if (store instanceof DElementStore) {
proxyDelegateKey_ = ((DElementStore) store).getStoreKey();
} else {
//TODO Some other mechanism to get the key
}
}
@Override
public Long getStoreKey() {
if (delegateKey_ == null) {
if (provisionalDelegateKey_ != null) {
Object delegate = getStoreDelegate();
if (delegate != null) {
if (delegate instanceof Database) {
String rid = ((Database) delegate).getReplicaID();
delegateKey_ = NoteCoordinate.Utils.getLongFromReplid(rid);
} else {
//TODO Some other mechanism to get the key
}
}
}
}
return delegateKey_;
}
@Override
public Long getProxyStoreKey() {
if (proxyDelegateKey_ == null) {
if (provisionalProxyDelegateKey_ != null) {
// System.out.println("Setting up proxy key using provisional delegate " + provisionalProxyDelegateKey_);
Object delegate = getProxyStoreDelegate();
if (delegate != null) {
if (delegate instanceof Database) {
String rid = ((Database) delegate).getReplicaID();
proxyDelegateKey_ = NoteCoordinate.Utils.getLongFromReplid(rid);
// System.out.println("Proxy database is " + System.identityHashCode(this) + " at "
// + ((Database) delegate).getApiPath() + " (" + ((Database) getStoreDelegate()).getApiPath() + ")");
// Throwable t = new Throwable();
// t.printStackTrace();
} else {
//TODO Some other mechanism to get the key
}
}
}
}
return proxyDelegateKey_;
}
@Override
public void setStoreKey(final Long storeKey) {
delegateKey_ = storeKey;
}
@Override
public void setStoreKey(final CharSequence storeKey) {
if (DominoUtils.isReplicaId(storeKey)) {
setStoreKey(NoteCoordinate.Utils.getLongFromReplid(storeKey));
} else {
if (storeKey.toString().contains("!!")) {
provisionalDelegateKey_ = storeKey;
} else {
provisionalDelegateKey_ = storeKey;
}
}
}
@Override
public void setProxyStoreKey(final Long storeKey) {
proxyDelegateKey_ = storeKey;
}
@Override
public void setProxyStoreKey(final CharSequence storeKey) {
if (DominoUtils.isReplicaId(storeKey)) {
setProxyStoreKey(NoteCoordinate.Utils.getLongFromReplid(storeKey));
} else {
if (storeKey.toString().contains("!!")) {
this.provisionalProxyDelegateKey_ = storeKey;
} else {
this.provisionalProxyDelegateKey_ = storeKey;
}
}
}
protected Object localizeKey(final Object id) {
if (id instanceof CharSequence) {
String idStr = id.toString();
if (idStr.length() > 16) {
String prefix = idStr.substring(0, 16);
String keyStr = NoteCoordinate.Utils.getReplidFromLong(getStoreKey());
// System.out.println("TEMP DEBUG: prefix on key is " + prefix + " while store key is " + keyStr);
if (prefix.equalsIgnoreCase(keyStr)) {
String localKey = idStr.substring(16);
// System.out.println("TEMP DEBUG: adding element with local key " + localKey);
return localKey;
} else {
return idStr;
}
} else {
return idStr;
}
} else {
return id;
}
}
@Override
public Vertex addVertex(final Object id) {
Vertex result = null;
Element chk = getCachedElement(id, Vertex.class);
if (chk != null) {
result = (Vertex) chk;
} else {
Object localkey = localizeKey(id);
Map<String, Object> delegate = addElementDelegate(localkey, Vertex.class);
if (delegate != null) {
if (isProxied()) {
result = setupProxy(delegate, (Serializable) id);
} else {
DVertex vertex = new DVertex(getConfiguration().getGraph(), delegate);
result = vertex;
}
getElementCache().put(result.getId(), result);
getKeyCache().put(id, (NoteCoordinate) result.getId()); //TODO shouldn't force NoteCoordinate, but it covers all current use cases
getConfiguration().getGraph().startTransaction(result);
}
}
return result;
}
@Override
public Vertex getVertex(final Object id) {
return (Vertex) getElement(id, Vertex.class);
}
@Override
public void removeVertex(final Vertex vertex) {
startTransaction(vertex);
DVertex dv = (DVertex) vertex;
Iterable<Edge> edges = dv.getEdges(Direction.BOTH);
if (edges != null) {
int i = 0;
try {
if (edges instanceof List) {
ListIterator<Edge> li = ((List<Edge>) edges).listIterator();
while (li.hasNext()) {
getConfiguration().getGraph().removeEdge(li.next(), dv);
// li.remove();
i++;
}
} else {
for (Edge edge : edges) {
getConfiguration().getGraph().removeEdge(edge, dv);
i++;
}
}
} catch (Exception e) {
System.err.println("Problem with a " + dv.getClass().getName() + " with id " + dv.getId() + " on edgelist "
+ (edges == null ? "null" : edges.getClass().getName()) + " on iteration " + i);
DominoUtils.handleException(e);
}
}
removeCache(vertex);
dv._remove();
}
@Override
public Edge addEdge(final Object id) {
Edge result = null;
Element chk = getCachedElement(id, Edge.class);
if (chk != null) {
result = (Edge) chk;
} else {
Object localkey = localizeKey(id);
Map<String, Object> delegate = addElementDelegate(localkey, Edge.class);
if (delegate != null) {
DEdge edge = new DEdge(getConfiguration().getGraph(), delegate);
result = edge;
getElementCache().put(result.getId(), result);
getKeyCache().put(id, (NoteCoordinate) result.getId()); //TODO shouldn't force NoteCoordinate, but it covers all current use cases
getConfiguration().getGraph().startTransaction(result);
}
}
return result;
}
protected Element getCachedElement(final Object id, final Class<? extends Element> type) {
if (id == null)
return null;
Element chk = getElementCache().get(id);
if (chk == null) {
NoteCoordinate nc = getKeyCache().get(id);
if (nc != null) {
chk = getElementCache().get(nc);
}
}
if (chk != null) {
if (type.isAssignableFrom(chk.getClass())) {
return chk;
} else {
throw new IllegalStateException("Requested id of " + String.valueOf(id) + " is already in cache but is a "
+ chk.getClass().getName());
}
}
return null;
}
public Element getElement(final Object id, final Class<? extends Element> type) throws IllegalStateException {
Element result = null;
Element chk = getCachedElement(id, Element.class);
if (chk != null) {
result = chk;
} else {
boolean isProxiedSource = false;
Object delegate = null;
if (id instanceof NoteCoordinate && isProxied()) {
NoteCoordinate nc = (NoteCoordinate) id;
if (getStoreKey().equals(nc.getReplicaLong())) {
//this is a request for a vertex out of the proxied store, not the proxy itself
// System.out.println("TEMP DEBUG Attempted to get a proxied source vertex at " + nc.toString());
// Throwable t = new Throwable();
// t.printStackTrace();
Database db = (Database) getStoreDelegate();
String unid = nc.getUNID();
delegate = db.getDocumentByUNID(unid, true);
if (delegate != null) {
isProxiedSource = true;
// System.out.println("TEMP DEBUG Got our original source from the proxy's proxiedid");
}
}
}
if (delegate == null) {
Object localkey = localizeKey(id);
// try {
delegate = findElementDelegate(localkey, type);
// } catch (IllegalStateException ise) {
// ise.printStackTrace();
// }
}
if (delegate != null) {
if (delegate instanceof Element) {
result = (Element) delegate;
} else if (delegate instanceof Document) {
if (isProxiedSource) {
DVertex vertex = new DVertex(getConfiguration().getGraph(), (Document) delegate);
result = vertex;
} else if (((Document) delegate).hasItem("$Index")) {
DVertex vertex = new DVertex(getConfiguration().getGraph(), (Document) delegate);
result = vertex;
} else {
Object typeChk = ((Document) delegate).get(org.openntf.domino.graph2.DElement.TYPE_FIELD);
String strChk = org.openntf.domino.utils.TypeUtils.toString(typeChk);
if (org.openntf.domino.graph2.DVertex.GRAPH_TYPE_VALUE.equals(strChk)) {
DVertex vertex = new DVertex(getConfiguration().getGraph(), (Document) delegate);
result = vertex;
} else if (org.openntf.domino.graph2.DEdge.GRAPH_TYPE_VALUE.equals(strChk)) {
DEdge edge = new DEdge(getConfiguration().getGraph(), (Document) delegate);
result = edge;
} else {
DVertex vertex = new DVertex(getConfiguration().getGraph(), (Document) delegate);
result = vertex;
}
}
} else if (delegate instanceof ViewEntry) {
if (id instanceof ViewEntryCoordinate) {
ViewEntryCoordinate vec = (ViewEntryCoordinate) id;
String entryType = vec.getEntryType();
if (entryType.startsWith("E")) {
DEdge edge = new DEntryEdge(getConfiguration().getGraph(), (ViewEntry) delegate, (ViewEntryCoordinate) id, this);
result = edge;
} else if (entryType.startsWith("V")) {
ViewEntry entry = (ViewEntry) delegate;
if (entry.isCategory()) {
Map<String, Object> delegateMap = new LinkedHashMap<String, Object>();
delegateMap.put("value", entry.getCategoryValue());
delegateMap.put("position", entry.getPosition());
delegateMap.put("noteid", entry.getNoteID());
DCategoryVertex vertex = new DCategoryVertex(getConfiguration().getGraph(), delegateMap,
entry.getParentView());
vertex.delegateKey_ = vec;
result = vertex;
}
}
}
}
getElementCache().put(result.getId(), result);
getKeyCache().put(id, (NoteCoordinate) result.getId()); //TODO shouldn't force NoteCoordinate, but it covers all current use cases
}
}
return result;
}
@Override
public Element getElement(final Object id) throws IllegalStateException {
return getElement(id, Element.class);
}
@Override
public Edge getEdge(final Object id) {
return (Edge) getElement(id, Edge.class);
}
@Override
public void removeEdge(final Edge edge) {
if (edge instanceof DEdge) {
if (org.openntf.domino.ViewEntry.class.equals(((DEdge) edge).getDelegateType())) {
throw new UnsupportedOperationException("ViewEntry edges cannot be removed.");
}
}
startTransaction(edge);
Vertex in = edge.getVertex(Direction.IN);
((DVertex) in).removeEdge(edge);
Vertex out = edge.getVertex(Direction.OUT);
((DVertex) out).removeEdge(edge);
removeCache(edge);
((DEdge) edge)._remove();
}
@Override
public void removeEdge(final Edge edge, final Vertex removingVertex) {
if (edge instanceof DEdge) {
if (org.openntf.domino.ViewEntry.class.equals(((DEdge) edge).getDelegateType())) {
throw new UnsupportedOperationException("ViewEntry edges cannot be removed.");
}
}
startTransaction(edge);
Vertex in = edge.getVertex(Direction.IN);
if (!in.equals(removingVertex)) {
((DVertex) in).removeEdge(edge);
}
Vertex out = edge.getVertex(Direction.OUT);
if (!out.equals(removingVertex)) {
((DVertex) out).removeEdge(edge);
}
removeCache(edge);
((DEdge) edge)._remove();
}
private void startTransaction(final Element element) {
getConfiguration().getGraph().startTransaction(element);
}
private void removeCache(final Element element) {
Object key = element.getId();
getElementCache().remove(key);
getKeyCache().remove(key);
}
@Override
public boolean isProxied() {
// Object pDelegate = getProxyStoreDelegate();
boolean result = getProxyStoreKey() != null;
// if (!result) {
// System.out.println("Checking proxy status on store " + System.identityHashCode(this) + " in thread "
// + System.identityHashCode(Thread.currentThread()));
// Throwable t = new Throwable();
// t.printStackTrace();
// }
return result;
}
protected Serializable getKeyProperty(final Map<String, Object> delegate) {
Object result = null;
String key = "";
//TODO NTF map determination of key property
//first find out if this delegate has a key property
if (!Strings.isNullOrEmpty(key)) {
result = delegate.get(key);
}
return (Serializable) result;
}
public DProxyVertex wrapProxiedVertex(final Map<String, Object> delegate) {
// System.out.println("Wrapping a proxied vertex...");
DVertex vertex = new DVertex(getConfiguration().getGraph(), delegate);
Object pDelegate = getProxyStoreDelegate();
Serializable pKey = null;
Map<String, Object> proxyDelegate = null;
pKey = getKeyProperty(delegate);
if (pKey == null) {
if (delegate instanceof Document) {
pKey = ((Document) delegate).getMetaversalID();
} else {
//TODO future implementations...
}
}
if (pDelegate instanceof Database) {
Database pDb = ((Database) pDelegate);
// System.out.println("Creating proxy version in database " + pDb.getApiPath());
Document pDoc = pDb.getDocumentWithKey(pKey, true);
proxyDelegate = pDoc;
} else {
//TODO future implementations...
}
DProxyVertex result = new DProxyVertex(getConfiguration().getGraph(), vertex, proxyDelegate);
return result;
}
protected DProxyVertex setupProxy(final Object proxy, final Serializable originalKey) {
// System.out.println("TEMP DEBUG Setting up proxy vertex");
DProxyVertex result = new DProxyVertex(getConfiguration().getGraph(), (Map<String, Object>) proxy);
Object rawpid = result.getProxiedId();
DElement elem = (DElement) getConfiguration().getGraph().getElement(rawpid);
if (elem == null) {
rawpid = null;
}
if (rawpid == null) {
CustomProxyResolver resolver = getCustomProxyResolver();
if (resolver == null) {
System.err.println("No default resolver implemented yet");
throw new UnimplementedException("Non-custom resolution of proxied vertices not yet implemented");
} else {
// System.out.println("Resolving using a " + resolver.getClass().getName());
Map<String, Object> originalDelegate = resolver.getOriginalDelegate(originalKey);
if (originalDelegate instanceof Document) {
String pid = ((Document) originalDelegate).getMetaversalID();
NoteCoordinate nc = NoteCoordinate.Utils.getNoteCoordinate(pid);
// System.out.println("Setting up proxy with id " + nc.toString());
try {
result.setProxiedId(nc);
} catch (Throwable t) {
t.printStackTrace();
}
} else {
if (originalDelegate == null) {
// System.out.println("No original delegate found for key " + String.valueOf(originalKey));
} else {
// System.err.println("original delegate returned a " + originalDelegate.getClass().getName());
}
}
}
} else {
}
// System.out.println("Setup a proxy with an id of " + String.valueOf(result.getProxiedId()));
return result;
}
@Override
public Object findElementDelegate(final Object delegateKey, final Class<? extends Element> type) throws IllegalStateException,
IllegalArgumentException {
Object result = null;
Object del = null;
del = getStoreDelegate();
if (isProxied()) {
NoteCoordinate nc = null;
if (delegateKey instanceof NoteCoordinate) {
nc = (NoteCoordinate) delegateKey;
} else if (delegateKey instanceof CharSequence) {
nc = NoteCoordinate.Utils.getNoteCoordinate((CharSequence) delegateKey);
}
if (nc != null) {
long dbkey = nc.getReplicaLong();
if (getProxyStoreKey().equals(dbkey)) {
del = getProxyStoreDelegate();
}
// System.out.println("TEMP DEBUG Retrieving from proxied store");
}
}
if (del instanceof Database) {
Database db = (Database) del;
if (delegateKey instanceof Serializable) {
if (delegateKey instanceof ViewEntryCoordinate) {
result = ((ViewEntryCoordinate) delegateKey).getViewEntry();
} else if (delegateKey instanceof NoteCoordinate) {
String unid = ((NoteCoordinate) delegateKey).getUNID();
result = db.getDocumentWithKey(unid, false);
// System.out.println("Retrieved result using NoteCoordinate with unid " + unid);
} else if (delegateKey instanceof CharSequence) {
String skey = ((CharSequence) delegateKey).toString();
if (skey.length() > 50) {
String prefix = skey.subSequence(0, 2).toString();
String mid = skey.subSequence(2, 50).toString();
if ((prefix.equals("EC") || prefix.equals("ED") || prefix.equals("ET") || prefix.equals("EU"))
&& DominoUtils.isMetaversalId(mid)) {
ViewEntryCoordinate vec = ViewEntryCoordinate.Utils.getViewEntryCoordinate(skey);
result = vec.getViewEntry();
} else if ((prefix.equals("VC") || prefix.equals("VD") || prefix.equals("VT") || prefix.equals("VU"))
&& DominoUtils.isMetaversalId(mid)) {
ViewEntryCoordinate vec = ViewEntryCoordinate.Utils.getViewEntryCoordinate(skey);
result = vec.getViewEntry();
}
}
}
if (result == null) {
result = db.getDocumentWithKey((Serializable) delegateKey, false);
}
if (result != null) {
// System.out.println("TEMP DEBUG Checking for proxy status for type " + type.getSimpleName());
boolean isProxy = false;
if (result instanceof Document) {
isProxy = ((Document) result).hasItem(DProxyVertex.PROXY_ITEM);
}
if (isProxied() && (isProxy || Vertex.class.isAssignableFrom(type) || VertexFrame.class.isAssignableFrom(type))) {
// System.out.println("TEMP DEBUG Setting up a proxied vertex...");
result = setupProxy(result, (Serializable) delegateKey);
}
}
} else {
if (delegateKey != null) {
System.out.println("WARNING: Unknown delegatekey of type " + delegateKey.getClass().getName()
+ ". Creating a brand new delegate.");
}
//null is a perfectly valid key, since it means we want to let the system assign it.
result = db.createDocument();
// throw new IllegalArgumentException("Cannot find a delegate with a key of type "
// + (delegateKey == null ? "null" : delegateKey.getClass().getName()));
}
} else {
throw new IllegalStateException("ElementStore delegate is not a Database; it's a "
+ (del == null ? "null" : del.getClass().getName()) + ". We don't handle this case yet.");
//TODO NTF alternative strategies...
}
// if (result == null && Vertex.class.isAssignableFrom(type)) {
// if (isProxied()) {
// Object proxyDel = getProxyStoreDelegate();
// if (proxyDel instanceof Database) {
// Database db = (Database) proxyDel;
// if (delegateKey instanceof NoteCoordinate) {
// String unid = ((NoteCoordinate) delegateKey).getUNID();
// result = db.getDocumentWithKey(unid, false);
// } else {
// result = db.getDocumentWithKey((Serializable) delegateKey, false);
// }
// } else if (proxyDel instanceof DElementStore) {
// result = ((DElementStore) proxyDel).findElementDelegate(delegateKey, type);
// } else {
// //TODO NTF unimplemented
// }
// }
// }
// if (result == null) {
// System.out
// .println("Request with delegatekey " + delegateKey.getClass().getName() + " (" + delegateKey + ")" + " returned null");
// }
if (result != null) {
if (type.equals(Element.class)) {
return result;
}
if (result instanceof org.openntf.domino.ViewEntry) {
return result;
}
if (delegateKey instanceof NoteCoordinate && ((NoteCoordinate) delegateKey).isView()) {
return result;
}
Object typeChk = ((Map<String, Object>) result).get(org.openntf.domino.graph2.DElement.TYPE_FIELD);
String strChk = org.openntf.domino.utils.TypeUtils.toString(typeChk);
if (org.openntf.domino.utils.Strings.isBlankString(strChk)) {//NTF new delegate
if (Vertex.class.isAssignableFrom(type)) {
((Map<String, Object>) result).put(org.openntf.domino.graph2.DElement.TYPE_FIELD,
org.openntf.domino.graph2.DVertex.GRAPH_TYPE_VALUE);
} else if (Edge.class.isAssignableFrom(type)) {
((Map<String, Object>) result).put(org.openntf.domino.graph2.DElement.TYPE_FIELD,
org.openntf.domino.graph2.DEdge.GRAPH_TYPE_VALUE);
} else {
//Illegal request
}
} else {//NTF existing delegate that's a vertex
if (Vertex.class.isAssignableFrom(type) && org.openntf.domino.graph2.DVertex.GRAPH_TYPE_VALUE.equals(strChk)) {
//okay
} else if (Edge.class.isAssignableFrom(type) && org.openntf.domino.graph2.DEdge.GRAPH_TYPE_VALUE.equals(strChk)) {
//okay
} else {
throw new IllegalStateException("Requested id of " + String.valueOf(delegateKey)
+ " results in a delegate with a graph type of " + strChk);
}
}
}
return result;
}
@Override
public void removeElementDelegate(final Element element) {
if (element instanceof DElement) {
Object del = ((DElement) element).getDelegate();
if (del instanceof Document) {
((Document) del).remove(true);
} else {
System.err.println("Cannot remove a delegate of type " + (del == null ? "null" : del.getClass().getName()));
}
((DElement) element).setDelegate(null);
} else {
System.err.println("Cannot remove a delegate for element of type " + (element == null ? "null" : element.getClass().getName()));
}
}
protected Map<String, Object> addElementDelegate(final Object delegateKey, final Class<? extends Element> type) {
Map<String, Object> result = null;
// System.out.println("Adding a " + type.getName() + " to Element Store " + System.identityHashCode(this));
Object del = null;
if (isProxied()) {
del = getProxyStoreDelegate();
} else {
del = getStoreDelegate();
}
if (del instanceof Database) {
Database db = (Database) del;
if (delegateKey == null || delegateKey instanceof Serializable) {
result = db.getDocumentWithKey((Serializable) delegateKey, true);
} else {
throw new IllegalArgumentException("Cannot add a delegate with a key of type " + delegateKey.getClass().getName());
}
} else {
if (del == null) {
throw new IllegalStateException("Store delegate is null!");
} else {
throw new IllegalStateException("Store delegate is not a Database. It is a " + del.getClass().getName());
}
}
if (result != null) {
Object typeChk = result.get(org.openntf.domino.graph2.DElement.TYPE_FIELD);
String strChk = org.openntf.domino.utils.TypeUtils.toString(typeChk);
if (org.openntf.domino.utils.Strings.isBlankString(strChk)) {//NTF new delegate
// System.out.println("TEMP DEBUG: New delegate for key " + String.valueOf(delegateKey));
if (Vertex.class.isAssignableFrom(type)) {
// System.out.println("TEMP DEBUG: New vertex for key " + String.valueOf(delegateKey));
result.put(org.openntf.domino.graph2.DElement.TYPE_FIELD, org.openntf.domino.graph2.DVertex.GRAPH_TYPE_VALUE);
} else if (Edge.class.isAssignableFrom(type)) {
// System.out.println("TEMP DEBUG: New edge for key " + String.valueOf(delegateKey));
result.put(org.openntf.domino.graph2.DElement.TYPE_FIELD, org.openntf.domino.graph2.DEdge.GRAPH_TYPE_VALUE);
} else {
//Illegal request
}
} else {//NTF existing delegate
// System.out.println("TEMP DEBUG: Delegate already exists for " + String.valueOf(delegateKey));
if (Vertex.class.isAssignableFrom(type) && org.openntf.domino.graph2.DVertex.GRAPH_TYPE_VALUE.equals(strChk)) {
//okay
} else if (Edge.class.isAssignableFrom(type) && org.openntf.domino.graph2.DEdge.GRAPH_TYPE_VALUE.equals(strChk)) {
//okay
} else {
throw new IllegalStateException("Requested id of " + String.valueOf(delegateKey)
+ " results in a delegate with a graph type of " + strChk);
}
}
} else {
throw new IllegalStateException("Requested id of " + String.valueOf(delegateKey)
+ " results in a null delegate and therefore cannot be persisted.");
}
return result;
}
@Override
public void setConfiguration(final org.openntf.domino.graph2.DConfiguration config) {
configuration_ = config;
}
@Override
public DVertexIterable getVertices() {
return new DVertexIterable(this, getVertexIds());
}
@Override
public DEdgeIterable getEdges() {
return new DEdgeIterable(this, getEdgeIds());
}
@Override
public DElementIterable getElements(final String formulaFilter) {
return new DElementIterable(this, getElementIds(formulaFilter));
}
@Override
public DVertexIterable getVertices(final String formulaFilter) {
return new DVertexIterable(this, getVertexIds(formulaFilter));
}
@Override
public DEdgeIterable getEdges(final String formulaFilter) {
return new DEdgeIterable(this, getEdgeIds(formulaFilter));
}
@Override
public DVertexIterable getVertices(final String key, final Object value) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getVertexFormula(key, value);
return getVertices(formulaFilter);
}
@Override
public DEdgeIterable getEdges(final String key, final Object value) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getEdgeFormula(key, value);
return getEdges(formulaFilter);
}
@Override
public DElementIterable getElements(final String key, final Object value) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getElementFormula(key, value);
return getElements(formulaFilter);
}
@Override
public Set<Vertex> getCachedVertices() {
FastSet<Vertex> result = new FastSet<Vertex>();
for (Element elem : getElementCache().values()) {
if (elem instanceof Vertex) {
result.add((Vertex) elem);
}
}
return result.unmodifiable();
}
protected List<NoteCoordinate> getVertexIds() {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(org.openntf.domino.graph2.DVertex.FORMULA_FILTER);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
protected List<NoteCoordinate> getVertexIds(final String formulaFilter) {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(formulaFilter);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
@Override
public Set<Edge> getCachedEdges() {
FastSet<Edge> result = new FastSet<Edge>();
for (Element elem : getElementCache().values()) {
if (elem instanceof Edge) {
result.add((Edge) elem);
}
}
return result.unmodifiable();
}
protected List<NoteCoordinate> getEdgeIds() {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(org.openntf.domino.graph2.DEdge.FORMULA_FILTER);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
protected List<NoteCoordinate> getEdgeIds(final String formulaFilter) {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(formulaFilter);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
protected List<NoteCoordinate> getElementIds() {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(org.openntf.domino.graph2.DEdge.FORMULA_FILTER + " | "
+ org.openntf.domino.graph2.DVertex.FORMULA_FILTER);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
protected List<NoteCoordinate> getElementIds(final String formulaFilter) {
FastTable<NoteCoordinate> result = new FastTable<NoteCoordinate>();
Object raw = getStoreDelegate();
if (raw instanceof Database) {
Database db = (Database) raw;
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectDocuments(true);
nc.setSelectionFormula(formulaFilter);
nc.buildCollection();
for (String noteid : nc) {
result.add(NoteCoordinate.Utils.getNoteCoordinate(nc, noteid));
}
} else {
//TODO NTF implement alternative
throw new IllegalStateException("Non-Domino implementations not yet available");
}
return result;
}
@Override
public DIdentityFactory getIdentityFactory() {
return identityFactory_;
}
@Override
public void setIdentityFactory(final DIdentityFactory identFactory) {
identityFactory_ = identFactory;
}
@Override
public Object getIdentity(final Class<?> type, final Object context, final Object... args) {
DIdentityFactory factory = getIdentityFactory();
if (factory != null) {
return factory.getId(this, type, context, args);
}
return null;
}
@Override
public void setCustomProxyResolver(final CustomProxyResolver resolver) {
proxyResolver_ = resolver;
resolver.setProxiedElementStore(this);
}
protected CustomProxyResolver getCustomProxyResolver() {
return proxyResolver_;
}
@Override
public void flushCache() {
keyCache_ = null;
elementCache_ = null;
}
}