package org.openntf.domino.graph2.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.openntf.domino.big.NoteCoordinate; import org.openntf.domino.big.NoteList; import org.openntf.domino.graph2.DEdgeList; import org.openntf.domino.utils.DominoUtils; import com.tinkerpop.blueprints.Direction; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Vertex; public class DFastEdgeList implements org.openntf.domino.graph2.DEdgeList { protected final DVertex sourceVertex_; protected final DGraph parentGraph_; protected List<NoteCoordinate> delegate_; protected boolean isUnique_; protected String label_; protected String storeid_; public static class DFastEdgeIterator implements ListIterator<Edge> { private ListIterator<NoteCoordinate> delegate_; private DVertex source_; private DGraph parent_; public DFastEdgeIterator(final DVertex source, final DGraph parent, final ListIterator<NoteCoordinate> delegate) { source_ = source; parent_ = parent; delegate_ = delegate; } @Override public void add(final Edge arg0) { delegate_.add(getNC(arg0)); } @Override public boolean hasNext() { return delegate_.hasNext(); } @Override public boolean hasPrevious() { return delegate_.hasPrevious(); } @Override public Edge next() { Edge result = null; try { result = parent_.getEdge(delegate_.next()); } catch (Throwable t) { System.err .println("Exception caught iterating an edge list. This is most likely caused by data corruption, typically because a replicaid changed. Bypassing for now..."); result = next(); } return result; } @Override public int nextIndex() { return delegate_.nextIndex(); } @Override public Edge previous() { try { return parent_.getEdge(delegate_.previous()); } catch (Throwable t) { System.err .println("Exception caught iterating an edge list. This is most likely caused by data corruption, typically because a replicaid changed. Bypassing for now..."); return previous(); } } @Override public int previousIndex() { return delegate_.previousIndex(); } @Override public void remove() { delegate_.remove(); } @Override public void set(final Edge arg0) { delegate_.set(getNC(arg0)); } } private static NoteCoordinate getNC(final Edge edge) { Object rawid = edge.getId(); if (rawid instanceof NoteCoordinate) { return (NoteCoordinate) rawid; } return null; } private static Collection<NoteCoordinate> getNCs(final Collection<?> arg0) { if (arg0 == null) return null; Collection<NoteCoordinate> ncs = new ArrayList<NoteCoordinate>(); for (Object raw : arg0) { if (raw instanceof Edge) { ncs.add(getNC((Edge) raw)); } } return ncs; } public DFastEdgeList(final DVertex source, final DGraph parent, final NoteList notelist, final String label) { sourceVertex_ = source; delegate_ = Collections.synchronizedList(notelist); parentGraph_ = parent; label_ = label; if (!notelist.isEmpty()) { NoteCoordinate nc = notelist.get(0); storeid_ = nc.getReplicaId(); } // Factory.println("DFastEdgeList " + label + " initialized for source vertex " + source.getId() + " , size " + delegate_.size()); // if (delegate_.size() > 0) { // Throwable t = new Throwable(); // t.printStackTrace(); // } } @Deprecated public DFastEdgeList(final DVertex source, final DGraph parent, final NoteList notelist) { sourceVertex_ = source; delegate_ = Collections.synchronizedList(notelist); parentGraph_ = parent; if (!notelist.isEmpty()) { NoteCoordinate nc = notelist.get(0); storeid_ = nc.getReplicaId(); } // Factory.println("DFastEdgeList initialized for source vertex " + source.getId() + " , size " + delegate_.size()); // if (delegate_.size() > 0) { // Throwable t = new Throwable(); // t.printStackTrace(); // } } // Throwable t_ = null; @Override public boolean add(final Edge arg0) { // System.out.println("Adding an edge to a DFastEdgeList"); NoteCoordinate nc = getNC(arg0); if (storeid_ == null) { storeid_ = nc.getReplicaId(); } if (!delegate_.contains(nc)) { // if ("DirectedBy".equals(label_)) { // t_ = new Throwable(); // } return delegate_.add(nc); } else { // if ("DirectedBy".equals(label_)) { // org.openntf.domino.utils.Factory.println("TEMP DEBUG Stopping an add of edge " + arg0.getId() // + " because it is already in the list. Here's where it's trying to add..."); // Throwable t = new Throwable(); // t.printStackTrace(); // if (t_ != null) { // org.openntf.domino.utils.Factory.println("TEMP DEBUG And here is the prior call stack..."); // t_.printStackTrace(); // } else { // Factory.println("TEMP DEBUG prior stack trace is null!??!"); // } // } return false; } } @Override public void add(final int arg0, final Edge arg1) { NoteCoordinate nc = getNC(arg1); if (storeid_ == null) { storeid_ = nc.getReplicaId(); } delegate_.add(arg0, nc); } @Override public boolean addAll(final Collection<? extends Edge> arg0) { return delegate_.addAll(getNCs(arg0)); } @Override public boolean addAll(final int arg0, final Collection<? extends Edge> arg1) { return delegate_.addAll(arg0, getNCs(arg1)); } @Override public void clear() { delegate_.clear(); } @Override public boolean contains(final Object arg0) { if (arg0 == null) return false; if (arg0 instanceof Edge) { NoteCoordinate nc = getNC((Edge) arg0); return delegate_.contains(nc); } else if (arg0 instanceof NoteCoordinate) { return delegate_.contains(arg0); } else if (arg0 instanceof CharSequence) { NoteCoordinate nc = NoteCoordinate.Utils.getNoteCoordinate((CharSequence) arg0); return delegate_.contains(nc); } else { throw new IllegalArgumentException("Cannot check whether a DFastEdgeList contains an object of type " + arg0.getClass().getName()); } } @Override public boolean containsAll(final Collection<?> arg0) { boolean result = true; for (Object raw : arg0) { result = contains(raw); if (!result) { break; } } return result; } @Override public Edge get(final int arg0) { NoteCoordinate nc = delegate_.get(arg0); return parentGraph_.getEdge(nc); } @Override public int indexOf(final Object arg0) { if (arg0 == null) return -1; if (arg0 instanceof Edge) { NoteCoordinate nc = getNC((Edge) arg0); return delegate_.indexOf(nc); } else if (arg0 instanceof NoteCoordinate) { return delegate_.indexOf(arg0); } else if (arg0 instanceof CharSequence) { NoteCoordinate nc = NoteCoordinate.Utils.getNoteCoordinate((CharSequence) arg0); return delegate_.indexOf(nc); } else { throw new IllegalArgumentException("Cannot get the index of an object of type " + arg0.getClass().getName()); } } @Override public boolean isEmpty() { return delegate_.isEmpty(); } @Override public Iterator<Edge> iterator() { return new DFastEdgeIterator(sourceVertex_, parentGraph_, delegate_.listIterator()); } @Override public int lastIndexOf(final Object arg0) { if (arg0 == null) return -1; if (arg0 instanceof Edge) { NoteCoordinate nc = getNC((Edge) arg0); return delegate_.lastIndexOf(nc); } else if (arg0 instanceof NoteCoordinate) { return delegate_.lastIndexOf(arg0); } else if (arg0 instanceof CharSequence) { NoteCoordinate nc = NoteCoordinate.Utils.getNoteCoordinate((CharSequence) arg0); return delegate_.lastIndexOf(nc); } else { throw new IllegalArgumentException("Cannot get the index of an object of type " + arg0.getClass().getName()); } } @Override public ListIterator<Edge> listIterator() { return new DFastEdgeIterator(sourceVertex_, parentGraph_, delegate_.listIterator()); } @Override public ListIterator<Edge> listIterator(final int arg0) { return new DFastEdgeIterator(sourceVertex_, parentGraph_, delegate_.listIterator(arg0)); } @Override public Edge remove(final int arg0) { NoteCoordinate nc = delegate_.remove(arg0); return parentGraph_.getEdge(nc); } @Override public boolean remove(final Object arg0) { if (arg0 == null) return false; if (arg0 instanceof Edge) { NoteCoordinate nc = getNC((Edge) arg0); return delegate_.remove(nc); } else if (arg0 instanceof NoteCoordinate) { return delegate_.remove(arg0); } else if (arg0 instanceof CharSequence) { NoteCoordinate nc = NoteCoordinate.Utils.getNoteCoordinate((CharSequence) arg0); return delegate_.remove(nc); } else { throw new IllegalArgumentException("Cannot remove an object of type " + arg0.getClass().getName()); } } @Override public boolean removeAll(final Collection<?> arg0) { boolean result = false; for (Object raw : arg0) { if (remove(raw)) result = true; } return result; } @Override public boolean retainAll(final Collection<?> arg0) { return delegate_.retainAll(getNCs(arg0)); } @Override public Edge set(final int arg0, final Edge arg1) { NoteCoordinate nc = delegate_.set(arg0, getNC(arg1)); if (storeid_ == null) { storeid_ = nc.getReplicaId(); } return parentGraph_.getEdge(nc); } @Override public int size() { return delegate_.size(); } @Override public List<Edge> subList(final int arg0, final int arg1) { DFastEdgeList result = new DFastEdgeList(sourceVertex_, parentGraph_, (NoteList) delegate_.subList(arg0, arg1), label_); // result.setLabel(label_); result.setUnique(isUnique_); return result; } @Override public Object[] toArray() { return delegate_.toArray(); } @Override public <T> T[] toArray(final T[] arg0) { return delegate_.toArray(arg0); } @Override public DEdgeList atomic() { return this; } @Override public DEdgeList unmodifiable() { return this; } @Override public Edge findEdge(final Vertex toVertex) { Edge result = null; Object toId = toVertex.getId(); Object fromId = sourceVertex_.getId(); if (isUnique() && !isEmpty()) { if (toId instanceof NoteCoordinate && fromId instanceof NoteCoordinate) { String toString = ((NoteCoordinate) toId).toString(); String fromString = ((NoteCoordinate) fromId).toString(); String testString1 = DominoUtils.toUnid(toString + getLabel() + fromString); String testString2 = DominoUtils.toUnid(toString + getLabel() + fromString); NoteCoordinate nc1 = NoteCoordinate.Utils.getNoteCoordinate(storeid_, testString1); NoteCoordinate nc2 = NoteCoordinate.Utils.getNoteCoordinate(storeid_, testString2); if (contains(nc1)) { result = parentGraph_.getEdge(nc1); } else if (contains(nc2)) { result = parentGraph_.getEdge(nc2); } } else { //NTF then we go back to the old way... } } if (result == null && this.size() > 0 && !isUnique()) { for (Edge edge : this) { if (edge instanceof DEdge) { DEdge dedge = (DEdge) edge; if (toId.equals(dedge.getOtherVertexId(sourceVertex_))) { result = dedge; break; } } else { if (edge != null) { Vertex inVertex = edge.getVertex(Direction.IN); if (fromId.equals(inVertex.getId())) { if (toId.equals(edge.getVertex(Direction.OUT))) { result = edge; break; } } else if (toId.equals(inVertex.getId())) { result = edge; break; } } } } } else { // System.out.println("DEBUG: No edges defined in EdgeList"); } return result; } @Override public DEdgeList applyFilter(final String key, final Object value) { DEdgeList result = new org.openntf.domino.graph2.impl.DEdgeList(sourceVertex_); if (this.size() > 0) { for (Edge edge : this) { if (edge instanceof DEdge) { DEdge dedge = (DEdge) edge; if (value.equals(dedge.getProperty(key))) { result.add(edge); } } } } return result; } @Override public DVertexList toVertexList() { // System.out.println("TEMP DEBUG Converting an edge list to a vertex list"); DVertexList result = new DVertexList(sourceVertex_); if (this.size() > 0) { for (Edge edge : this) { if (edge instanceof DEdge) { DEdge dedge = (DEdge) edge; try { DVertex vert = (DVertex) dedge.getOtherVertex(sourceVertex_); result.add(vert); } catch (Throwable t) { t.printStackTrace(); } } else { // System.out.println("TEMP DEBUG EdgeList didn't have a DEdge. It had a " + edge.getClass().getName()); } } } else { // System.out.println("TEMP DEBUG EdgeList size is not greater than 0."); } return result; } @Override public boolean isUnique() { return isUnique_; } @Override public void setUnique(final boolean isUnique) { isUnique_ = true; } @Override public String getLabel() { return label_; } @Override public void setLabel(final String label) { label_ = label; // Factory.println("Setting label to " + label); } }