/**
* Copyright (c) 2002-2010 "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 Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.index.impl.sortedtree;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
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.index.impl.btree.BTree;
/**
* A sorted list of nodes (structured as a tree in neo4j).
*
* This class isn't ready for general usage yet and use of it is discouraged.
*
* @deprecated Builds in {@link BTree}, which also is deprecated.
*/
public class SortedTree
{
static enum RelTypes implements RelationshipType
{
TREE_ROOT,
SUB_TREE,
// a relationship type where relationship actually is the *key entry*
KEY_ENTRY
};
private final GraphDatabaseService graphDb;
private final Comparator<Node> nodeComparator;
private TreeNode treeRoot;
/**
* @param graphDb the {@link GraphDatabaseService} instance.
* @param rootNode the root of this tree.
* @param nodeComparator the {@link Comparator} to use to sort the nodes.
* It's important to use the same {@link Comparator} for a given root node
* to get the expected results.
*/
public SortedTree( GraphDatabaseService graphDb, Node rootNode,
Comparator<Node> nodeComparator )
{
this.graphDb = graphDb;
this.nodeComparator = nodeComparator;
this.treeRoot = new TreeNode( this, rootNode );
}
void makeRoot( TreeNode newRoot )
{
Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(
RelTypes.TREE_ROOT, Direction.INCOMING );
Node startNode = rel.getStartNode();
rel.delete();
startNode.createRelationshipTo( newRoot.getUnderlyingNode(),
RelTypes.TREE_ROOT );
treeRoot = newRoot;
}
/**
* Deletes this sorted tree.
*/
public void delete()
{
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 )
{
Relationship rel = treeRoot.getUnderlyingNode().getSingleRelationship(
RelTypes.TREE_ROOT, Direction.INCOMING );
treeRoot.delete( commitInterval, 0);
rel.delete();
}
/**
* 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 boolean addNode( Node node )
{
return treeRoot.addEntry( node, true );
}
/**
* @param node the {@link Node} to check if it's in the list.
* @return {@code true} if this list contains the node, otherwise
* {@code false}.
*/
public boolean containsNode( Node node )
{
return treeRoot.containsEntry( node );
}
/**
* 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 removeNode( Node node )
{
return treeRoot.removeEntry( node );
}
int getOrder()
{
return 9;
}
GraphDatabaseService getGraphDb()
{
return graphDb;
}
/**
* @return the {@link Comparator} used for this list.
*/
public Comparator<Node> getComparator()
{
return nodeComparator;
}
/**
* @return all the nodes in this list.
*/
public Iterable<Node> getSortedNodes()
{
List<Node> nodeList = new ArrayList<Node>();
traverseTreeNode( treeRoot, nodeList );
return nodeList;
}
private void traverseTreeNode( TreeNode currentNode, List<Node> nodeList )
{
NodeEntry entry = currentNode.getFirstEntry();
while ( entry != null )
{
TreeNode beforeTree = entry.getBeforeSubTree();
if ( beforeTree != null )
{
traverseTreeNode( beforeTree, nodeList );
}
nodeList.add( entry.getTheNode() );
NodeEntry nextEntry = entry.getNextKey();
if ( nextEntry == null )
{
TreeNode afterTree = entry.getAfterSubTree();
if ( afterTree != null )
{
traverseTreeNode( afterTree, nodeList );
}
}
entry = nextEntry;
}
}
}