package org.openntf.domino.graph2.annotations; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import org.openntf.domino.graph2.DGraphUtils; import org.openntf.domino.graph2.impl.DFramedTransactionalGraph; import org.openntf.domino.graph2.impl.DVertex; import org.openntf.domino.graph2.impl.DVertexList; import org.openntf.domino.utils.TypeUtils; import com.tinkerpop.blueprints.Edge; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.frames.FramedGraph; import com.tinkerpop.frames.VertexFrame; import com.tinkerpop.frames.structures.FramedVertexIterable; public class FramedVertexList<T extends VertexFrame> extends FramedVertexIterable<T> implements List<T> { public static class FramedListIterator<T> implements ListIterator<T> { protected final Class<T> kind_; // protected final Direction direction_; protected final ListIterator<Vertex> iterator_; protected final FramedGraph<? extends Graph> framedGraph_; public FramedListIterator(final FramedGraph<? extends Graph> graph, final ListIterator<Vertex> iterator, final Class<T> kind/*, Direction direction*/) { kind_ = kind; // direction_ = direction; iterator_ = iterator; framedGraph_ = graph; } @Override public void add(final Object arg0) { if (arg0 == null) return; if (kind_.isAssignableFrom(arg0.getClass())) { iterator_.add(((VertexFrame) kind_.cast(arg0)).asVertex()); } else if (arg0 instanceof Edge) { iterator_.add((Vertex) arg0); } else { throw new IllegalArgumentException("Cannot add an object of type " + arg0.getClass().getName() + " to an iterator of " + kind_.getName()); } } @Override public boolean hasNext() { return iterator_.hasNext(); } @Override public boolean hasPrevious() { return iterator_.hasPrevious(); } @Override public T next() { Vertex v = iterator_.next(); T result = null; result = framedGraph_.frame(v, kind_); return result; } @Override public int nextIndex() { return iterator_.nextIndex(); } @Override public T previous() { return framedGraph_.frame(iterator_.previous(), kind_); } @Override public int previousIndex() { return iterator_.previousIndex(); } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void set(final Object arg0) { if (arg0 instanceof Vertex) { iterator_.set((Vertex) arg0); } else if (kind_.isAssignableFrom(arg0.getClass())) { iterator_.set(((VertexFrame) kind_.cast(arg0)).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an iterator of " + kind_.getName()); } } } protected List<Vertex> list_; protected Vertex sourceVertex_; public FramedVertexList(final FramedGraph<? extends Graph> framedGraph, final Vertex sourceVertex, final Iterable<Vertex> list, final Class<T> kind) { super(framedGraph, list, kind); // Throwable t = new Throwable(); // t.printStackTrace(); sourceVertex_ = sourceVertex; if (list instanceof List) { list_ = (List<Vertex>) list; } else { list_ = new ArrayList<Vertex>(); Iterator<Vertex> itty = list.iterator(); while (itty.hasNext()) { list_.add(itty.next()); } } } @SuppressWarnings({ "unchecked", "rawtypes" }) public FramedVertexList<T> applyFilter(final String key, final Object value) { DVertexList vertList = new DVertexList((DVertex) sourceVertex_); if (this.size() > 0) { for (VertexFrame vertex : this) { try { if ("@type".equals(key)) { if (DGraphUtils.isType(vertex, TypeUtils.toString(value))) { vertList.add((DVertex) vertex.asVertex()); } } else { Object vertexVal = DGraphUtils.getFramedProperty(getGraph(), vertex, key); if (value.equals(TypeUtils.toString(vertexVal))) { vertList.add((DVertex) vertex.asVertex()); } } } catch (Throwable t) { t.printStackTrace(); } } } FramedVertexList result = new FramedVertexList(getGraph(), sourceVertex_, vertList, this.kind); return result; } public DFramedTransactionalGraph<?> getGraph() { return (DFramedTransactionalGraph<?>) framedGraph; } @Override public boolean add(final T arg0) { return list_.add(arg0.asVertex()); } @Override public void add(final int arg0, final T arg1) { list_.add(arg0, arg1.asVertex()); } protected static List<Vertex> convertToVertexes(final Collection<?> arg0) { List<Vertex> result = new ArrayList<Vertex>(arg0.size()); for (Object raw : arg0) { if (raw instanceof Vertex) { result.add((Vertex) raw); } else if (raw instanceof VertexFrame) { result.add(((VertexFrame) raw).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an EdgeFrame iterator"); } } return result; } protected static List<Vertex> convertToVertexes(final Object[] arg0) { List<Vertex> result = new ArrayList<Vertex>(arg0.length); for (Object raw : arg0) { if (raw == null) { } else if (raw instanceof Vertex) { result.add((Vertex) raw); } else if (raw instanceof VertexFrame) { result.add(((VertexFrame) raw).asVertex()); } else if (raw.getClass().isArray()) { result.addAll(convertToVertexes((Object[]) raw)); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to List<Vertex>"); } } return result; } @Override public boolean addAll(final Collection<? extends T> arg0) { return list_.addAll(convertToVertexes(arg0)); } @Override public boolean addAll(final int arg0, final Collection<? extends T> arg1) { return list_.addAll(arg0, convertToVertexes(arg1)); } @Override public void clear() { list_.clear(); } @Override public boolean contains(final Object arg0) { if (arg0 instanceof Vertex) { return list_.contains(arg0); } else if (kind.isAssignableFrom(arg0.getClass())) { return list_.contains(((VertexFrame) kind.cast(arg0)).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an iterator of " + kind.getName()); } } @Override public boolean containsAll(final Collection<?> arg0) { return list_.containsAll(convertToVertexes(arg0)); } @Override public T get(final int arg0) { return framedGraph.frame(list_.get(arg0), kind); } @Override public int indexOf(final Object arg0) { if (arg0 instanceof Vertex) { return list_.indexOf(arg0); } else if (kind.isAssignableFrom(arg0.getClass())) { return list_.indexOf(((VertexFrame) kind.cast(arg0)).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an iterator of " + kind.getName()); } } @Override public boolean isEmpty() { return list_.isEmpty(); } @Override public int lastIndexOf(final Object arg0) { if (arg0 instanceof Vertex) { return list_.lastIndexOf(arg0); } else if (kind.isAssignableFrom(arg0.getClass())) { return list_.lastIndexOf(((VertexFrame) kind.cast(arg0)).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an iterator of " + kind.getName()); } } @Override public ListIterator<T> listIterator() { return new FramedListIterator<T>(framedGraph, list_.listIterator(), kind); } @Override public ListIterator<T> listIterator(final int arg0) { return new FramedListIterator<T>(framedGraph, list_.listIterator(arg0), kind); } @Override public Iterator<T> iterator() { ListIterator<Vertex> iterator = list_.listIterator(); if (iterator == null) System.err.println("ListIterator IS NULL from list of type " + list_.getClass().getName()); return new FramedListIterator<T>(framedGraph, iterator, kind); } @Override public T remove(final int arg0) { Vertex e = list_.remove(arg0); return framedGraph.frame(e, kind); } @Override public boolean remove(final Object arg0) { if (arg0 instanceof Vertex) { return list_.remove(arg0); } else if (kind.isAssignableFrom(arg0.getClass())) { return list_.remove(((VertexFrame) kind.cast(arg0)).asVertex()); } else { throw new IllegalArgumentException("Cannot set an object of type " + arg0.getClass().getName() + " to an iterator of " + kind.getName()); } } @Override public boolean removeAll(final Collection<?> arg0) { return list_.removeAll(convertToVertexes(arg0)); } @Override public boolean retainAll(final Collection<?> arg0) { return list_.retainAll(convertToVertexes(arg0)); } @Override public T set(final int arg0, final T arg1) { Vertex edge = arg1.asVertex(); list_.set(arg0, edge); return arg1; } @Override public int size() { return list_.size(); } @Override public List<T> subList(final int arg0, int arg1) { if (arg1 > list_.size()) { arg1 = list_.size(); } List<Vertex> sublist = list_.subList(arg0, arg1); return new FramedVertexList<T>(framedGraph, sourceVertex_, sublist, kind); } @Override public Object[] toArray() { int size = list_.size(); Object[] result = new Object[size]; for (int i = 0; i < size; i++) { Vertex e = list_.get(i); result[i] = framedGraph.frame(e, kind); } return result; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public <U> U[] toArray(final U[] arg0) { int size = list_.size(); Class c = arg0.getClass().getComponentType(); U[] result = (U[]) Array.newInstance(c, size); int i = 0; for (Vertex v : list_) { if (v != null) { result[i++] = (U) framedGraph.frame(v, kind); } } // for (int i = 0; i < size; i++) { // Vertex e = list_.get(i); // result[i] = (U) framedGraph.frame(e, kind); // } if (i < size) { result = Arrays.copyOf(result, i); } return result; } public static List<Vertex> toVertexList(final VertexFrame[] vfArray) { List<Vertex> result = new ArrayList<Vertex>(vfArray.length); for (VertexFrame vf : vfArray) { if (vf != null) { result.add(vf.asVertex()); } } return result; } private static final VertexFrame[] VF = new VertexFrame[1]; public FramedVertexList<T> sortBy(final List<CharSequence> keys, final boolean desc) { //TODO: optimize! This should really be resorting the Vertex list but using the VertexFrame as the criteria VertexFrame[] array = toArray(VF); Arrays.sort(array, new DGraphUtils.VertexFrameComparator(getGraph(), keys, desc)); return new FramedVertexList<T>(framedGraph, sourceVertex_, toVertexList(array), kind); } }