Package com.orientechnologies.orient.core.db.graph

Source Code of com.orientechnologies.orient.core.db.graph.OGraphVertex

/*
* Copyright 1999-2010 Luca Garulli (l.garulli--at--orientechnologies.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.orientechnologies.orient.core.db.graph;

import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Set;

import com.orientechnologies.orient.core.annotation.OAfterDeserialization;
import com.orientechnologies.orient.core.exception.OGraphException;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.type.ODocumentWrapper;

/**
* GraphDB Vertex class. It represent the vertex (or node) in the graph. The Vertex can have custom properties. You can read/write
* them using respectively get/set methods. The Vertex can be connected to other Vertexes using edges. The Vertex keeps the edges
* separated: "inEdges" for the incoming edges and "outEdges" for the outgoing edges.
*
* @see OGraphEdge
*/
public class OGraphVertex extends OGraphElement implements Cloneable {
  private SoftReference<Set<OGraphEdge>>  inEdges;
  private SoftReference<Set<OGraphEdge>>  outEdges;

  public OGraphVertex(final ODatabaseGraphTx iDatabase) {
    super(iDatabase, OGraphDatabase.VERTEX_CLASS_NAME);
  }

  public OGraphVertex(final ODatabaseGraphTx iDatabase, final String iClassName) {
    super(iDatabase, iClassName != null ? iClassName : OGraphDatabase.VERTEX_CLASS_NAME);
  }

  public OGraphVertex(final ODatabaseGraphTx iDatabase, final ODocument iDocument) {
    super(iDatabase, iDocument);
  }

  public OGraphVertex(final ODatabaseGraphTx iDatabase, final ODocument iDocument, final String iFetchPlan) {
    super(iDatabase, iDocument);
  }

  @SuppressWarnings("unchecked")
  @Override
  public <RET extends ODocumentWrapper> RET save() {
    super.save();
    if (database != null)
      database.registerPojo(this, document);
    return (RET) this;
  }

  public Set<OGraphVertex> traverse(final int iStartLevel, final int iEndLevel) {
    return null;
  }

  @Override
  public OGraphVertex clone() {
    return new OGraphVertex(database, document);
  }

  @Override
  @OAfterDeserialization
  public void fromStream(final ODocument iDocument) {
    super.fromStream(iDocument);
    document.setTrackingChanges(false);
    inEdges = outEdges = null;
  }

  /**
   * Create a link between the current vertex and the target one. The link is of type iClassName.
   *
   * @param iTargetVertex
   *          Target vertex where to create the connection
   * @param iClassName
   *          The name of the class to use for the Edge
   * @return The new edge created
   */
  @SuppressWarnings("unchecked")
  public OGraphEdge link(final OGraphVertex iTargetVertex, final String iClassName) {
    if (iTargetVertex == null)
      throw new IllegalArgumentException("Missed the target vertex");

    // CREATE THE EDGE BETWEEN ME AND THE TARGET
    final OGraphEdge edge = new OGraphEdge(database, iClassName, this, iTargetVertex);
    getOutEdges().add(edge);

    Set<ODocument> recordEdges = ((Set<ODocument>) document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES));
    if (recordEdges == null) {
      recordEdges = new HashSet<ODocument>();
      document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES, recordEdges);
    }
    recordEdges.add(edge.getDocument());
    document.setDirty();

    // INSERT INTO THE INGOING EDGES OF TARGET
    iTargetVertex.getInEdges().add(edge);

    recordEdges = ((Set<ODocument>) iTargetVertex.getDocument().field(OGraphDatabase.VERTEX_FIELD_IN_EDGES));
    if (recordEdges == null) {
      recordEdges = new HashSet<ODocument>();
      iTargetVertex.getDocument().field(OGraphDatabase.VERTEX_FIELD_IN_EDGES, recordEdges);
    }

    recordEdges.add(edge.getDocument());
    iTargetVertex.getDocument().setDirty();

    return edge;
  }

  /**
   * Create a link between the current vertex and the target one.
   *
   * @param iTargetVertex
   *          Target vertex where to create the connection
   * @return The new edge created
   */
  public OGraphEdge link(final OGraphVertex iTargetVertex) {
    return link(iTargetVertex, null);
  }

  /**
   * Remove the link between the current vertex and the target one.
   *
   * @param iTargetVertex
   *          Target vertex where to remove the connection
   * @return Current vertex (useful for fluent calls)
   */
  public OGraphVertex unlink(final OGraphVertex iTargetVertex) {
    if (iTargetVertex == null)
      throw new IllegalArgumentException("Missed the target vertex");

    unlink(database, document, iTargetVertex.getDocument());

    return this;
  }

  /**
   * Returns true if the vertex has at least one incoming edge, otherwise false.
   */
  public boolean hasInEdges() {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);
    return docs != null && !docs.isEmpty();
  }

  /**
   * Returns true if the vertex has at least one outgoing edge, otherwise false.
   */
  public boolean hasOutEdges() {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);
    return docs != null && !docs.isEmpty();
  }

  /**
   * Returns the incoming edges of current node. If there are no edged, then an empty set is returned.
   */
  public Set<OGraphEdge> getInEdges() {
    return getInEdges(null);
  }

  /**
   * Returns the incoming edges of current node having the requested label. If there are no edged, then an empty set is returned.
   */
  public Set<OGraphEdge> getInEdges(final String iEdgeLabel) {
    Set<OGraphEdge> temp = inEdges != null ? inEdges.get() : null;

    if (temp == null) {
      if (iEdgeLabel == null)
        temp = new HashSet<OGraphEdge>();
      inEdges = new SoftReference<Set<OGraphEdge>>(temp);

      final Set<Object> docs = document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);

      if (docs != null) {
        // TRANSFORM ALL THE ARCS
        ODocument doc;
        for (Object o : docs) {
          if (o instanceof ODocument)
            doc = (ODocument) o;
          else
            doc = database.getRecordById((ORID) o);

          if (iEdgeLabel != null && !iEdgeLabel.equals(doc.field(OGraphDatabase.LABEL)))
            continue;

          temp.add((OGraphEdge) database.getUserObjectByRecord(doc, null));
        }
      }
    } else if (iEdgeLabel != null) {
      // FILTER THE EXISTENT COLLECTION
      HashSet<OGraphEdge> filtered = new HashSet<OGraphEdge>();
      for (OGraphEdge e : temp) {
        if (iEdgeLabel.equals(e.get(OGraphDatabase.LABEL)))
          filtered.add(e);
      }
      temp = filtered;
    }

    return temp;
  }

  /**
   * Returns all the outgoing edges of current node. If there are no edged, then an empty set is returned.
   */
  public Set<OGraphEdge> getOutEdges() {
    return getOutEdges(null);
  }

  /**
   * Returns the outgoing edge of current node having the requested label. If there are no edged, then an empty set is returned.
   */
  public Set<OGraphEdge> getOutEdges(final String iEdgeLabel) {
    Set<OGraphEdge> temp = outEdges != null ? outEdges.get() : null;

    if (temp == null) {
      temp = new HashSet<OGraphEdge>();
      if (iEdgeLabel == null)
        outEdges = new SoftReference<Set<OGraphEdge>>(temp);

      final Set<Object> docs = document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);

      if (docs != null) {
        // TRANSFORM ALL THE ARCS
        ODocument doc;
        for (Object o : docs) {
          if (o instanceof ODocument)
            doc = (ODocument) o;
          else
            doc = database.getRecordById((ORID) o);

          if (iEdgeLabel != null && !iEdgeLabel.equals(doc.field(OGraphDatabase.LABEL)))
            continue;

          temp.add((OGraphEdge) database.getUserObjectByRecord(doc, null));
        }
      }
    } else if (iEdgeLabel != null) {
      // FILTER THE EXISTENT COLLECTION
      HashSet<OGraphEdge> filtered = new HashSet<OGraphEdge>();
      for (OGraphEdge e : temp) {
        if (iEdgeLabel.equals(e.get(OGraphDatabase.LABEL)))
          filtered.add(e);
      }
      temp = filtered;
    }

    return temp;
  }

  /**
   * Returns the set of Vertexes from the outgoing edges. It avoids to unmarshall edges.
   */
  @SuppressWarnings("unchecked")
  public Set<OGraphVertex> browseOutEdgesVertexes() {
    final Set<OGraphVertex> resultset = new HashSet<OGraphVertex>();

    Set<OGraphEdge> temp = outEdges != null ? outEdges.get() : null;

    if (temp == null) {
      final Set<ODocument> docEdges = (Set<ODocument>) document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);

      // TRANSFORM ALL THE EDGES
      if (docEdges != null)
        for (ODocument d : docEdges) {
          resultset.add((OGraphVertex) database.getUserObjectByRecord((ODocument) d.field(OGraphDatabase.EDGE_FIELD_IN), null));
        }
    } else {
      for (OGraphEdge edge : temp) {
        resultset.add(edge.getIn());
      }
    }

    return resultset;
  }

  /**
   * Returns the set of Vertexes from the incoming edges. It avoids to unmarshall edges.
   */
  @SuppressWarnings("unchecked")
  public Set<OGraphVertex> browseInEdgesVertexes() {
    final Set<OGraphVertex> resultset = new HashSet<OGraphVertex>();

    Set<OGraphEdge> temp = inEdges != null ? inEdges.get() : null;

    if (temp == null) {
      final Set<ODocument> docEdges = (Set<ODocument>) document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);

      // TRANSFORM ALL THE EDGES
      if (docEdges != null)
        for (ODocument d : docEdges) {
          resultset.add((OGraphVertex) database.getUserObjectByRecord((ODocument) d.field(OGraphDatabase.EDGE_FIELD_OUT), null));
        }
    } else {
      for (OGraphEdge edge : temp) {
        resultset.add(edge.getOut());
      }
    }

    return resultset;
  }

  public ODocument findInVertex(final OGraphVertex iVertexDocument) {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);
    if (docs == null || docs.size() == 0)
      return null;

    for (ODocument d : docs) {
      if (d.<ODocument>field(OGraphDatabase.EDGE_FIELD_IN).equals(iVertexDocument.getDocument()))
        return d;
    }

    return null;
  }

  public ODocument findOutVertex(final OGraphVertex iVertexDocument) {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);
    if (docs == null || docs.size() == 0)
      return null;

    for (ODocument d : docs) {
      if (d.<ODocument>field(OGraphDatabase.EDGE_FIELD_OUT).equals(iVertexDocument.getDocument()))
        return d;
    }

    return null;
  }

  public int getInEdgeCount() {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);
    return docs == null ? 0 : docs.size();
  }

  public int getOutEdgeCount() {
    final Set<ODocument> docs = document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);
    return docs == null ? 0 : docs.size();
  }

  @Override
  public void reset() {
    document = null;
    inEdges = null;
    outEdges = null;
  }

  @SuppressWarnings("unchecked")
  @Override
  public void delete() {
    // DELETE ALL THE IN-OUT EDGES FROM RAM
    if (inEdges != null && inEdges.get() != null)
      inEdges.get().clear();
    inEdges = null;

    if (outEdges != null && outEdges.get() != null)
      outEdges.get().clear();
    outEdges = null;

    Set<ODocument> docs = (Set<ODocument>) document.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);
    if (docs != null)
      for (ODocument doc : docs.toArray(new ODocument[docs.size()]))
        OGraphEdge.delete(database, doc);

    docs = (Set<ODocument>) document.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);
    if (docs != null)
      for (ODocument doc : docs.toArray(new ODocument[docs.size()]))
        OGraphEdge.delete(database, doc);

    database.unregisterPojo(this, document);

    document.delete();
    document = null;
  }

  public void onEvent(final ORecord<?> iDocument, final EVENT iEvent) {
    if (iEvent == EVENT.UNLOAD) {
      outEdges = null;
      inEdges = null;
    }
  }

  /**
   * Unlinks all the edges between iSourceVertex and iTargetVertex
   *
   * @param iDatabase
   * @param iSourceVertex
   * @param iTargetVertex
   */
  public static void unlink(final ODatabaseGraphTx iDatabase, final ODocument iSourceVertex, final ODocument iTargetVertex) {
    if (iTargetVertex == null)
      throw new IllegalArgumentException("Missed the target vertex");

    if (iDatabase.existsUserObjectByRID(iSourceVertex.getIdentity())) {
      // WORK ALSO WITH IN MEMORY OBJECTS

      final OGraphVertex vertex = (OGraphVertex) iDatabase.getUserObjectByRecord(iSourceVertex, null);
      // REMOVE THE EDGE OBJECT
      if (vertex.outEdges != null && vertex.outEdges.get() != null) {
        for (OGraphEdge e : vertex.outEdges.get())
          if (e.getIn().getDocument().equals(iTargetVertex)) {
            vertex.outEdges.get().remove(e);
            break;
          }
      }
    }

    if (iDatabase.existsUserObjectByRID(iTargetVertex.getIdentity())) {
      // WORK ALSO WITH IN MEMORY OBJECTS

      final OGraphVertex vertex = (OGraphVertex) iDatabase.getUserObjectByRecord(iTargetVertex, null);
      // REMOVE THE EDGE OBJECT FROM THE TARGET VERTEX
      if (vertex.inEdges != null && vertex.inEdges.get() != null) {
        for (OGraphEdge e : vertex.inEdges.get())
          if (e.getOut().getDocument().equals(iSourceVertex)) {
            vertex.inEdges.get().remove(e);
            break;
          }
      }
    }

    // REMOVE THE EDGE DOCUMENT
    ODocument edge = null;
    Set<ODocument> docs = iSourceVertex.field(OGraphDatabase.VERTEX_FIELD_OUT_EDGES);
    if (docs != null) {
      for (ODocument d : docs)
        if (d.<ODocument>field(OGraphDatabase.EDGE_FIELD_IN).equals(iTargetVertex)) {
          docs.remove(d);
          edge = d;
          break;
        }
    }

    if (edge == null)
      throw new OGraphException("Edge not found between the ougoing edges");

    iSourceVertex.setDirty();
    iSourceVertex.save();

    docs = iTargetVertex.field(OGraphDatabase.VERTEX_FIELD_IN_EDGES);

    // REMOVE THE EDGE DOCUMENT FROM THE TARGET VERTEX
    if (docs != null) {
      for (ODocument d : docs)
        if (d.<ODocument>field(OGraphDatabase.EDGE_FIELD_IN).equals(iTargetVertex)) {
          docs.remove(d);
          break;
        }
    }

    iTargetVertex.setDirty();
    iTargetVertex.save();

    edge.delete();
  }
}
TOP

Related Classes of com.orientechnologies.orient.core.db.graph.OGraphVertex

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.