Package org.openntf.domino.graph

Source Code of org.openntf.domino.graph.DominoGraph$DominoGraphException

package org.openntf.domino.graph;

import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import javolution.util.FastMap;
import javolution.util.FastSet;

import org.openntf.domino.Document;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewEntryCollection;
import org.openntf.domino.transactions.DatabaseTransaction;
import org.openntf.domino.utils.DominoUtils;
import org.openntf.domino.utils.Factory;

import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Features;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.MetaGraph;
import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.util.DefaultGraphQuery;

@SuppressWarnings("rawtypes")
public class DominoGraph implements Graph, MetaGraph, TransactionalGraph {
  public static class DominoGraphException extends RuntimeException {

    private static final long serialVersionUID = 1L;
    final String message_;
    final DominoElement elem1_;
    final DominoElement elem2_;

    public DominoGraphException(final String message) {
      super(message);
      message_ = message;
      elem1_ = null;
      elem2_ = null;
    }

    public DominoGraphException(final String message, final DominoElement element) {
      super(message);
      message_ = message;
      elem1_ = element;
      elem2_ = null;

    }

    public DominoGraphException(final String message, final DominoElement element1, final DominoElement element2) {
      super(message);
      message_ = message;
      elem1_ = element1;
      elem2_ = element2;
    }
  }

  private static final Logger log_ = Logger.getLogger(DominoGraph.class.getName());

  public static final Set<String> EMPTY_IDS = Collections.emptySet();

  public static final String EDGE_VIEW_NAME = "(_OPEN_Edges)";
  public static final String VERTEX_VIEW_NAME = "(_OPEN_Vertices)";
  private static final Features FEATURES = new Features();
  public static final boolean COMPRESS_IDS = false;

  public static SortedSet<? extends Element> sortElements(final Iterable<? extends Element> elements, final String[] sortproperties) {
    //    StringBuilder sb = new StringBuilder();
    //    for (String prop : sortproperties) {
    //      sb.append(prop + ", ");
    //    }
    //    System.out.println("Sorting elements from String properties: " + sb.toString());
    Comparator<Element> comp = new ElementComparator(sortproperties);
    SortedSet<Element> result = new TreeSet<Element>(comp);
    for (Object e : elements) {
      if (e instanceof Element) {
        result.add((Element) e);
      }
    }
    return Collections.unmodifiableSortedSet(result);
  }

  public static SortedSet<? extends Element> sortElements(final Iterable<? extends Element> elements,
      final IDominoProperties[] sortproperties) {
    Comparator<Element> comp = new ElementComparator(sortproperties);
    SortedSet<Element> result = new TreeSet<Element>(comp);
    for (Object e : elements) {
      if (e instanceof Element) {
        result.add((Element) e);
      }
    }
    return Collections.unmodifiableSortedSet(result);
  }

  @SuppressWarnings("unchecked")
  public static SortedSet<? extends Edge> sortEdges(final Iterable<? extends Edge> elements, final String[] sortproperties) {
    return (SortedSet<Edge>) sortElements(elements, sortproperties);
  }

  @SuppressWarnings("unchecked")
  public static SortedSet<? extends Vertex> sortVertexes(final Iterable<? extends Vertex> elements, final String[] sortproperties) {
    return (SortedSet<Vertex>) sortElements(elements, sortproperties);
  }

  @SuppressWarnings("unchecked")
  public static SortedSet<? extends Edge> sortEdges(final Iterable<? extends Edge> elements, final IDominoProperties[] sortproperties) {
    return (SortedSet<Edge>) sortElements(elements, sortproperties);
  }

  @SuppressWarnings("unchecked")
  public static SortedSet<? extends Vertex> sortVertexes(final Iterable<? extends Vertex> elements,
      final IDominoProperties[] sortproperties) {
    return (SortedSet<Vertex>) sortElements(elements, sortproperties);
  }

  static {
    DominoGraph.FEATURES.supportsDuplicateEdges = true;
    DominoGraph.FEATURES.supportsSelfLoops = true;
    DominoGraph.FEATURES.supportsSerializableObjectProperty = true;
    DominoGraph.FEATURES.supportsBooleanProperty = true;
    DominoGraph.FEATURES.supportsDoubleProperty = true;
    DominoGraph.FEATURES.supportsFloatProperty = true;
    DominoGraph.FEATURES.supportsIntegerProperty = true;
    DominoGraph.FEATURES.supportsPrimitiveArrayProperty = true;
    DominoGraph.FEATURES.supportsUniformListProperty = true;
    DominoGraph.FEATURES.supportsMixedListProperty = true;
    DominoGraph.FEATURES.supportsLongProperty = true;
    DominoGraph.FEATURES.supportsMapProperty = true;
    DominoGraph.FEATURES.supportsStringProperty = true;

    DominoGraph.FEATURES.ignoresSuppliedIds = false;

    DominoGraph.FEATURES.isWrapper = false;

    DominoGraph.FEATURES.supportsIndices = false;
    DominoGraph.FEATURES.supportsKeyIndices = false;
    DominoGraph.FEATURES.supportsVertexKeyIndex = false;
    DominoGraph.FEATURES.supportsEdgeKeyIndex = false;
    DominoGraph.FEATURES.supportsVertexIndex = false;
    DominoGraph.FEATURES.supportsEdgeIndex = false;
    DominoGraph.FEATURES.supportsTransactions = true;
    DominoGraph.FEATURES.supportsVertexIteration = false;
    DominoGraph.FEATURES.supportsEdgeIteration = false;
    DominoGraph.FEATURES.supportsEdgeRetrieval = true;
    DominoGraph.FEATURES.supportsVertexProperties = true;
    DominoGraph.FEATURES.supportsEdgeProperties = true;
    DominoGraph.FEATURES.supportsThreadedTransactions = true;
    DominoGraph.FEATURES.isPersistent = true;

  }

  private java.util.Map<Object, Element> cache_;

  private String filepath_;
  private String server_;
  protected transient Map<String, IEdgeHelper> edgeHelpers_ = new FastMap<String, IEdgeHelper>();

  public DominoGraph(final org.openntf.domino.Database database) {
    setRawDatabase(database);
  }

  public IEdgeHelper getHelper(final String key) {
    IEdgeHelper helper = edgeHelpers_.get(key);
    return helper;
  }

  public IEdgeHelper getHelper(final IDominoEdgeType edgeType) {
    return getHelper(edgeType.getLabel());
  }

  public Set<IEdgeHelper> findHelpers(final Vertex in, final Vertex out) {
    Set<IEdgeHelper> result = new FastSet<IEdgeHelper>();
    if (in == null || out == null) {
      return result;
    }
    Class<?> inCls = in.getClass();
    Class<?> outCls = out.getClass();
    for (IEdgeHelper helper : edgeHelpers_.values()) {
      boolean inChk = helper.getInType().isAssignableFrom(inCls);
      boolean outChk = helper.getOutType().isAssignableFrom(outCls);
      if (inChk && outChk) {
        result.add(helper);
      }
    }
    return result;
  }

  public void addHelper(final String key, final Class<? extends Vertex> inType, final Class<? extends Vertex> outType) {
    addHelper(key, inType, outType, true, key);
  }

  public void addHelper(final String key, final Class<? extends Vertex> inType, final Class<? extends Vertex> outType,
      final boolean unique) {
    addHelper(key, inType, outType, unique, key);
  }

  public void addHelper(final String key, final Class<? extends Vertex> inType, final Class<? extends Vertex> outType,
      final boolean unique, final String label) {
    if (getHelper(key) == null) {
      edgeHelpers_.put(key, new AbstractEdgeHelper(this, label, inType, outType, unique));
    }
  }

  public void addHelper(final String key, final IEdgeHelper helper) {
    if (getHelper(key) == null) {
      edgeHelpers_.put(key, helper);
    }
  }

  public void removeHelper(final String key) {
    edgeHelpers_.remove(key);
  }

  public void setRawDatabase(final org.openntf.domino.Database database) {
    if (database != null) {
      server_ = database.getServer();
      filepath_ = database.getFilePath();
    }
  }

  private java.util.Map<Object, Element> getCache() {
    if (cache_ == null) {
      cache_ = new FastMap<Object, Element>().atomic();
    }
    return cache_;
  }

  public void cache(final Element elem) {
    putCache(elem);
  }

  private void putCache(final Element elem) {
    if (elem != null) {
      Map<Object, Element> cache = getCache();
      //      synchronized (cache) {
      cache.put(elem.getId(), elem);
      //      }
    }
  }

  private Element getCache(final Object id) {
    Map<Object, Element> cache = getCache();
    Element result = null;
    //    synchronized (cache) {
    result = cache.get(id);
    //    }
    return result;
  }

  private void removeCache(final Element elem) {
    Map<Object, Element> cache = getCache();
    //    synchronized (cache) {
    cache.remove(elem);
    //    }
  }

  private Set<Element> getCacheValues() {
    Map<Object, Element> cache = getCache();
    FastSet<Element> result = new FastSet<Element>();
    //    synchronized (cache) {
    result.addAll(cache.values());
    //    }
    return result.unmodifiable();
  }

  private void clearCache() {
    Map<Object, Element> cache = getCache();
    //    synchronized (cache) {
    try {
      cache.clear();
    } catch (Throwable t) {
      t.printStackTrace();
    }
    //    }
    clearDocumentCache();
  }

  @Override
  public Edge addEdge(Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
    startTransaction(null);
    if (id == null)
      id = DominoUtils.toUnid(outVertex.getId() + label + inVertex.getId());
    Document d = getDocument(id, true);
    d.replaceItemValue(DominoElement.TYPE_FIELD, DominoEdge.GRAPH_TYPE_VALUE);
    DominoEdge ed = new DominoEdge(this, d);
    putCache(ed);
    // putCache(outVertex);
    // putCache(inVertex);
    ed.setLabel(label);
    ed.setOutDoc((IDominoVertex) outVertex);
    ed.setInDoc((IDominoVertex) inVertex);
    return ed;
  }

  public Edge getEdge(final Vertex outVertex, final Vertex inVertex, final String label) {
    String id = DominoUtils.toUnid(outVertex.getId() + label + inVertex.getId());
    Edge result = getEdge(id);
    if (result != null) {
      ((DominoEdge) result).setOutDoc((IDominoVertex) outVertex);
      ((DominoEdge) result).setInDoc((IDominoVertex) inVertex);
    }
    return result;
  }

  public Edge getOrAddEdge(Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
    Edge result = null;
    if (id == null) {
      id = DominoUtils.toUnid(outVertex.getId() + label + inVertex.getId());
      result = getEdge(id);
      if (result != null) {
        ((DominoEdge) result).setLabel(label);
        ((DominoEdge) result).setOutDoc((IDominoVertex) outVertex);
        ((DominoEdge) result).setInDoc((IDominoVertex) inVertex);
      }
    }
    // if (result == null) {
    // for (Edge e : outVertex.getEdges(Direction.OUT, label)) {
    // Vertex v = e.getVertex(Direction.IN);
    // if (v.getId().equals(inVertex.getId())) {
    // result = e;
    // ((DominoEdge) result).setLabel(label);
    // ((DominoEdge) result).setOutDoc(outVertex);
    // ((DominoEdge) result).setInDoc(inVertex);
    // break;
    // }
    // }
    // }
    if (result == null) {
      result = addEdge(id, outVertex, inVertex, label);
    }
    return result;
  }

  @Override
  public Vertex addVertex(final Object id) {
    startTransaction(null);
    Document d = null;
    if (id == null) {
      d = getDocument(null, true);
    } else {
      String vid = DominoUtils.toUnid((Serializable) id);
      d = getDocument(vid, true);
    }

    d.replaceItemValue(DominoElement.TYPE_FIELD, DominoVertex.GRAPH_TYPE_VALUE);
    DominoVertex result = new DominoVertex(this, d);
    putCache(result);
    return result;
  }

  private org.openntf.domino.Database getDatabase() {
    return getRawSession().getDatabase(server_, filepath_);
  }

  public org.openntf.domino.Session getRawSession() {
    return Factory.getSession();
  }

  public org.openntf.domino.Database getRawDatabase() {
    return getDatabase();
  }

  Document getDocument(final Object id, final boolean createOnFail) {
    Document result = null;
    String unid = "";
    Map<String, Document> map = documentCache.get();
    if (id == null && createOnFail) {
      result = getRawDatabase().createDocument();
      //      synchronized (map) {
      map.put(result.getUniversalID(), result);
      //      }
    } else if (id instanceof String) {
      String sid = (String) id;
      if (DominoUtils.isUnid(sid)) {
        unid = sid;
      } else if (sid.length() > 32) {
        unid = DominoUtils.toUnid(sid);
      } else {

        unid = DominoUtils.toUnid(sid);
      }
    } else if (id instanceof Serializable) {
      unid = DominoUtils.toUnid((Serializable) id);
    }
    if (id != null && !DominoUtils.isUnid(unid)) {
      log_.log(Level.SEVERE, "ALERT! INVALID UNID FROM id type " + (id == null ? "null" : id.getClass().getName()) + ": " + id);
    }
    if (result == null) {

      result = map.get(unid);
      if (result == null) {
        result = getRawDatabase().getDocumentWithKey(unid, createOnFail);
        if (result != null) {
          String localUnid = result.getUniversalID();
          if (!unid.equalsIgnoreCase(localUnid)) {
            log_.log(Level.SEVERE, "UNIDs do not match! Expected: " + unid + ", Result: " + localUnid);
          }
          //          synchronized (map) {
          map.put(unid, result);
          //          }
        }
      }
    }
    // if (result == null && createOnFail) {
    // log_.log(Level.SEVERE, "Returning a null document for id " + String.valueOf(id)
    // + " even though createOnFail was true. This should be guaranteed to return a real document!");
    // }
    if (result == null && createOnFail) {
      log_.log(Level.SEVERE,
          "We are about to return a null result even though createOnFail was true. We should ALWAYS return a Document in that case. For key: "
              + String.valueOf(id) + " in database " + String.valueOf(filepath_));
      new RuntimeException().printStackTrace();
    }
    return result;
  }

  @Override
  public Edge getEdge(final Object id) {
    //see http://www.tinkerpop.com/docs/javadocs/blueprints/2.5.0/com/tinkerpop/blueprints/Graph.html#getEdge(java.lang.Object)
    Edge result = null;
    if (id == null) {
      //      Document d = getDocument(id, false);
      //      result = new DominoEdge(this, d);
      //      putCache(result);
      return null;
    } else {
      result = (Edge) getCache(id);
      if (result == null) {
        // System.out.println("Cache miss on edge with id " + id);
        Document d = getDocument(id, false);
        if (d != null) {
          result = new DominoEdge(this, d);
          putCache(result);
        }
      }

    }
    return result;
  }

  @Override
  public Iterable<Edge> getEdges() {
    FastSet<Edge> result = new FastSet<Edge>();
    ViewEntryCollection vec = getEdgeView().getAllEntries();
    for (ViewEntry entry : vec) {
      result.add(getEdge(entry.getUniversalID()));
    }

    return result.unmodifiable();
  }

  @Override
  public Iterable<Edge> getEdges(final String key, final Object value) {
    // TODO
    throw new UnsupportedOperationException();
  }

  public FastSet<Edge> getEdgesFromIds(final Set<String> set) {
    FastSet<Edge> result = new FastSet<Edge>();
    for (String id : set) {
      Edge edge = getEdge(id);
      if (edge != null) {
        result.add(edge);
      }
    }
    return result;
  }

  public Set<Edge> getEdgesFromIds(final Set<String> set, final String... labels) {
    FastSet<Edge> result = new FastSet<Edge>();
    for (String id : set) {
      Edge edge = getEdge(id);
      if (edge != null) {
        for (String label : labels) {
          if (label.equals(edge.getLabel())) {
            result.add(edge);
            break;
          }
        }
      }
    }
    return result;
  }

  private View getEdgeView() {
    View result = getRawDatabase().getView(DominoGraph.EDGE_VIEW_NAME);
    if (result == null) {
      result = getRawDatabase().createView(DominoGraph.EDGE_VIEW_NAME,
          "SELECT " + DominoElement.TYPE_FIELD + "=\"" + DominoEdge.GRAPH_TYPE_VALUE + "\"", null, false);
      org.openntf.domino.ViewColumn column1 = result.createColumn();
      column1.setTitle("Created");
      column1.setFormula("@Created");
      column1.setSortDescending(true);
    }
    return result;
  }

  @Override
  public Features getFeatures() {
    return DominoGraph.FEATURES;
  }

  @Override
  public Vertex getVertex(final Object id) {
    String vid = DominoUtils.toUnid((Serializable) id);
    Vertex result = (Vertex) getCache(vid);
    if (result == null) {
      Document d = getDocument(vid, false);
      if (d == null)
        return null;
      if (d.isDeleted()) {
        // System.out.println("Found vertex for id " + String.valueOf(id) + " but it's been deleted.");
        return null;
      }
      result = new DominoVertex(this, d);
      putCache(result);
    }
    return result;
  }

  private View getVertexView() {
    View result = getRawDatabase().getView(DominoGraph.VERTEX_VIEW_NAME);
    if (result == null) {
      result = getRawDatabase().createView(DominoGraph.VERTEX_VIEW_NAME,
          "SELECT " + DominoElement.TYPE_FIELD + "=\"" + DominoVertex.GRAPH_TYPE_VALUE + "\"", null, false);
      org.openntf.domino.ViewColumn column1 = result.createColumn();
      column1.setTitle("Created");
      column1.setFormula("@Created");
      column1.setSortDescending(true);
    }
    return result;
  }

  @Override
  public Iterable<Vertex> getVertices() {
    FastSet<Vertex> result = new FastSet<Vertex>();
    ViewEntryCollection vec = getVertexView().getAllEntries();
    for (ViewEntry entry : vec) {
      result.add(getVertex(entry.getUniversalID()));
    }
    return result.unmodifiable();
  }

  @Override
  public Iterable<Vertex> getVertices(final String key, final Object value) {
    // TODO Auto-generated method stub
    throw new UnsupportedOperationException();
  }

  @Override
  public GraphQuery query() {
    return new DefaultGraphQuery(this);
  }

  @Override
  public void removeEdge(final Edge edge) {
    startTransaction(edge);
    Vertex in = edge.getVertex(Direction.IN);
    ((DominoVertex) in).removeEdge(edge);
    Vertex out = edge.getVertex(Direction.OUT);
    ((DominoVertex) out).removeEdge(edge);
    removeCache(edge);
    ((DominoEdge) edge)._remove();
  }

  @Override
  public void removeVertex(final Vertex vertex) {
    startTransaction(vertex);
    DominoVertex dv = (DominoVertex) vertex;
    for (Edge edge : dv.getEdges(Direction.BOTH)) {
      removeEdge(edge);
    }
    removeCache(vertex);
    dv._remove();
  }

  @Override
  public void shutdown() {
    commit();
  }

  @Override
  public Object getRawGraph() {
    return getRawDatabase();
  }

  // private boolean inTransaction_ = false;
  private static ThreadLocal<DatabaseTransaction> txnHolder_ = new ThreadLocal<DatabaseTransaction>() {

  };

  public static void clearDocumentCache() {
    documentCache.set(null);
  }

  private static ThreadLocal<Map<String, Document>> documentCache = new ThreadLocal<Map<String, Document>>() {
    /*
     * (non-Javadoc)
     *
     * @see java.lang.ThreadLocal#initialValue()
     */
    @Override
    protected Map<String, Document> initialValue() {
      return new FastMap<String, Document>();
    }

    /*
     * (non-Javadoc)
     *
     * @see java.lang.ThreadLocal#get()
     */
    @Override
    public Map<String, Document> get() {
      Map<String, Document> map = super.get();
      if (map == null) {
        map = new FastMap<String, Document>();
        super.set(map);

      }
      return map;
    }

  };

  private DatabaseTransaction getTxn() {
    return getRawDatabase().getTransaction();
    //    return txnHolder_.get();
  }

  //  public void setTxn(final DatabaseTransaction txn) {
  //    txnHolder_.set(txn);
  //  }

  // private DatabaseTransaction txn_;

  public void startTransaction(final Element elem) {
    putCache(elem);
    if (getTxn() == null) {
      getRawDatabase().startTransaction();
      //      setTxn(getRawDatabase().startTransaction());
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see com.tinkerpop.blueprints.TransactionalGraph#stopTransaction(com.tinkerpop.blueprints.TransactionalGraph.Conclusion)
   */
  @Override
  @Deprecated
  @SuppressWarnings("deprecation")
  public void stopTransaction(final Conclusion conclusion) {
    // TODO Auto-generated method stub

  }

  public void commit(final boolean clearCache) {
    DatabaseTransaction txn = getTxn();
    if (txn != null) {
      if (getCache().size() > 0) {
        // System.out.println("Reapplying cache to " + getCache().size() + " elements...");
        int vCount = 0;
        Set<Element> elems = getCacheValues();
        for (Element elem : elems) {
          if (elem instanceof DominoElement) {
            ((DominoElement) elem).reapplyChanges();
          }
        }
      } else {
        // System.out.println("Element cache is empty (so what are we committing?)");
      }
      txn.commit();
      //      setTxn(null);
    }
    if (clearCache)
      clearCache();
    // System.out.println("Transaction complete");
  }

  /*
   * (non-Javadoc)
   *
   * @see com.tinkerpop.blueprints.TransactionalGraph#commit()
   */
  @Override
  public void commit() {
    commit(true);
  }

  /*
   * (non-Javadoc)
   *
   * @see com.tinkerpop.blueprints.TransactionalGraph#rollback()
   */
  @Override
  public void rollback() {
    DatabaseTransaction txn = getTxn();
    if (txn != null) {
      txn.rollback();
      //      setTxn(null);
    }
    clearCache();
    // System.out.println("Transaction rollbacked");
  }

}
TOP

Related Classes of org.openntf.domino.graph.DominoGraph$DominoGraphException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.