Package org.neo4j.collections.sortedtree

Source Code of org.neo4j.collections.sortedtree.SortedTree$NodeIterator

/**
* Copyright (c) 2002-2013 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.collections.sortedtree;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;

import org.neo4j.collections.NodeCollection;
import org.neo4j.collections.graphdb.PropertyComparator;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;

/**
* A sorted list of nodes (structured as a Btree in neo4j).
*/
public class SortedTree implements NodeCollection//Iterable<Relationship>
{

  public static final String TREE_NAME = "tree_name";
  public static final String IS_UNIQUE_INDEX = "is_unique_index";
  public static final String COMPARATOR_CLASS = "comparator_class";

    public static enum RelTypes implements RelationshipType
  {
    TREE_ROOT,
    SUB_TREE,
    // a relationship type where relationship actually is the *key entry*
    KEY_ENTRY,
    KEY_VALUE
  }

    private final Node baseNode;
    private final Comparator<Node> nodeComparator;
    private final String treeName;
  private final boolean isUniqueIndex;
  private TreeNode treeRoot;

    /**
     * Instantiate a previously stored SortedTree from the base node.
     *
     * @param baseNode the base node of the sorted tree.
     */
    public SortedTree( Node baseNode )
    {
        this.baseNode = baseNode;

        try
        {
            Relationship rel = baseNode.getSingleRelationship( RelTypes.TREE_ROOT, Direction.OUTGOING );
            String comparatorClass = (String) rel.getProperty( COMPARATOR_CLASS );
            this.nodeComparator = (Comparator<Node>) Class.forName( comparatorClass ).newInstance();
            this.treeName = (String) rel.getProperty( TREE_NAME );
            this.isUniqueIndex = (Boolean) rel.getProperty( IS_UNIQUE_INDEX );
            this.treeRoot = new TreeNode( this, rel.getEndNode() );
        }
        catch ( Exception e )
        {
            throw new IllegalStateException( "Unable to re-instantiate SortedTree from graph data structure.", e );
        }
    }

    /**
     * Create a new sorted tree within the graph database.
     *
   * @param graphDb the {@link org.neo4j.graphdb.GraphDatabaseService} instance.
     * @param nodeComparator the {@link java.util.Comparator} to use to sort the nodes.
     * @param isUniqueIndex determines if every entry in the tree needs to have a unique comparator value
     * @param treeName value set on both the TREE_ROOT and the KEY_VALUE relations.
     */
  public SortedTree( GraphDatabaseService graphDb, Comparator<Node> nodeComparator, boolean isUniqueIndex,
                       String treeName )
  {

        if (graphDb == null )
        {
            throw new IllegalArgumentException( "Graph Database must be provided when creating new SortedTree" );
        }
        this.baseNode = graphDb.createNode();

        Transaction tx = graphDb.beginTx();
        try
        {
            Node rootNode = graphDb.createNode();
            Relationship treeRootRelationship = baseNode.createRelationshipTo( rootNode, RelTypes.TREE_ROOT );
            this.treeRoot = new TreeNode( this, rootNode );
            baseNode.setProperty( NodeCollection.GRAPH_COLLECTION_CLASS, SortedTree.class.getName() );

            treeRootRelationship.setPropertyTREE_NAME, treeName );
            treeRootRelationship.setProperty( IS_UNIQUE_INDEX, isUniqueIndex );
            treeRootRelationship.setProperty( COMPARATOR_CLASS, nodeComparator.getClass().getName());

            this.treeName = treeName;
        this.isUniqueIndex = isUniqueIndex;
            this.nodeComparator = nodeComparator;

            tx.success();
        }
        finally
        {
            tx.finish();
        }
  }

    private void acquireLock(){
      Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(RelTypes.TREE_ROOT, Direction.INCOMING);
      rel.getStartNode().removeProperty("___dummy_property_to_acquire_lock_____");
    }

  void makeRoot( TreeNode newRoot )
  {
    Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(
      RelTypes.TREE_ROOT, Direction.INCOMING );
    Node startNode = rel.getStartNode();
    HashMap<String, Object> props = new HashMap<String, Object>();
    for(String key: rel.getPropertyKeys()){
      props.put(key, rel.getProperty(key));
    }
    rel.delete();
    Relationship newRel = startNode.createRelationshipTo( newRoot.getUnderlyingNode(),
      RelTypes.TREE_ROOT );
    for(String key: props.keySet()){
      newRel.setProperty(key, props.get(key));
    }
    treeRoot = newRoot;
  }

  /**
   * Deletes this sorted tree.
   */
  public void delete()
  {
    acquireLock();
    Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(
      RelTypes.TREE_ROOT, Direction.INCOMING );
    treeRoot.delete();
    rel.delete();
  }

  /**
   * Deletes this sorted tree using a commit interval.
   *
   * @param commitInterval number of entries to remove before a new
   * transaction is started
   */
  public void delete( int commitInterval )
  {
    acquireLock();
    Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(
      RelTypes.TREE_ROOT, Direction.INCOMING );
    treeRoot.delete( commitInterval, 0);
    rel.delete();
  }

    @Override
    public Node getBaseNode()
    {
        return baseNode;
    }

    /**
   * Adds a {@link Node} to this list.
   * @param node the {@link Node} to add.
   * @return {@code true} if this call modified the tree, i.e. if the node
   * wasn't already added.
   */
  public Relationship addNode( Node node )
  {
    acquireLock();
    return treeRoot.addEntry( node, true );
  }

    /**
     * @param node the {@link Node} to check if it's in the tree.
     * @return {@code true} if this list contains the node, otherwise
     * {@code false}.
     */
    public boolean containsNode( Node node )
    {
        return treeRoot.containsEntry( node );
    }


  protected <T> boolean containsValue(T val, PropertyComparator<T> comp) {
    return treeRoot.containsValue( val, comp );
  }

    protected <T> Iterable<Node> getWithValue(T val, PropertyComparator<T> comp){
      return treeRoot.getWithValue(val, comp);
    }


  /**
   * Removes the node from this list.
   * @param node the {@link Node} to remove from this list.
   * @return whether or not this call modified the list, i.e. if the node
   * existed in this list.
   */
  public boolean remove( Node node )
  {
    acquireLock();
    return treeRoot.removeEntry( node );
  }

  int getOrder()
  {
    return 25;
  }

  GraphDatabaseService getGraphDb()
  {
    return baseNode.getGraphDatabase();
  }

  String getTreeName(){
    return treeName;
  }

  TreeNode getTreeRoot(){
    return treeRoot;
  }


    /**
     * @return the {@link Comparator} used for this list.
     */
    public Comparator<Node> getComparator()
    {
        return nodeComparator;
    }

    /**
     * @return the {@link Comparator} used for this list.
     */
    public boolean isUniqueIndex()
    {
        return isUniqueIndex;
    }

    class NodeIterator implements Iterator<Node>{

      private TreeNode currentNode;

        NodeEntry entry = null;
        Iterator<Node> ni = null;
        NodeIterator bi = null;
        NodeIterator ai = null;
        int step = 0;

      NodeIterator(TreeNode currentNode){
        initTreeNode(currentNode);
      }

      private void initTreeNode(TreeNode currentNode){
        this.currentNode = currentNode;
        NodeEntry entry = (this.currentNode == null) null : currentNode.getFirstEntry();
        if(entry != null){
          initEntry(entry);
        }
      }

      private void initEntry(NodeEntry nodeEntry){
        this.entry = nodeEntry;
      TreeNode beforeTree = entry.getBeforeSubTree();
      if ( beforeTree != null )
      {
        bi = new NodeIterator(beforeTree);
      }
      ni = entry.getNodes().iterator();
      }

      private void initAfterEntry(NodeEntry entry){
            TreeNode afterTree = entry.getAfterSubTree();
            if ( afterTree != null )
            {
                ai = new NodeIterator( afterTree );
            }
      }

    @Override
    public boolean hasNext() {
      if(entry != null){
        if(bi != null && bi.hasNext()){
          return true;
        }else if(ni.hasNext()){
          return true;
        }else{
          return false;
        }
      }else{
        if(ai != null && ai.hasNext()){
          return true;
        }else return false;
      }
    }

    @Override
    public Node next() {
      if(bi != null && bi.hasNext()){
        return bi.next();
      }else if(ni.hasNext()){
        Node n = ni.next();
        if(!ni.hasNext()){
          initAfterEntry(entry);
          entry = entry.getNextKey();
          if(entry != null){
            initEntry(entry);
          }
        }
        return n;
      }else if(ai.hasNext()){
        return ai.next();
      }
      return null;
    }

    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }
    }

    class RelationshipIterator implements Iterator<Relationship>{

      private TreeNode currentNode;

        NodeEntry entry = null;
        Iterator<Relationship> ni = null;
        RelationshipIterator bi = null;
        RelationshipIterator ai = null;
        int step = 0;

      RelationshipIterator(TreeNode currentNode){
        initTreeNode(currentNode);
      }

      private void initTreeNode(TreeNode currentNode){
        this.currentNode = currentNode;
        NodeEntry entry = (this.currentNode == null) null : currentNode.getFirstEntry();
        if(entry != null){
          initEntry(entry);
        }
      }

      private void initEntry(NodeEntry nodeEntry){
        this.entry = nodeEntry;
      TreeNode beforeTree = entry.getBeforeSubTree();
      if ( beforeTree != null )
      {
        bi = new RelationshipIterator(beforeTree);
      }
      ni = entry.getRelationships().iterator();
      }

      private void initAfterEntry(NodeEntry entry){
            TreeNode afterTree = entry.getAfterSubTree();
            if ( afterTree != null )
            {
                ai = new RelationshipIterator( afterTree );
            }
      }

    @Override
    public boolean hasNext() {
      if(entry != null){
        if(bi != null && bi.hasNext()){
          return true;
        }else if(ni.hasNext()){
          return true;
        }else{
          return false;
        }
      }else{
        if(ai != null && ai.hasNext()){
          return true;
        }else return false;
      }
    }

    @Override
    public Relationship next() {
      if(bi != null && bi.hasNext()){
        return bi.next();
      }else if(ni.hasNext()){
        Relationship n = ni.next();
        if(!ni.hasNext()){
          initAfterEntry(entry);
          entry = entry.getNextKey();
          if(entry != null){
            initEntry(entry);
          }
        }
        return n;
      }else if(ai.hasNext()){
        return ai.next();
      }
      return null;
    }

    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }
    }

    public Iterator<Node> iterator(){
      return new NodeIterator(treeRoot);
    }

    @Override
    public Iterable<Relationship> getValueRelationships()
    {
        return new Iterable<Relationship>() {

            @Override
            public Iterator<Relationship> iterator()
            {
                return new RelationshipIterator( treeRoot );
            }
        };
    }
}
TOP

Related Classes of org.neo4j.collections.sortedtree.SortedTree$NodeIterator

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.