/*
* Licensed to "Neo Technology," Network Engine for Objects in Lund AB
* (http://neotechnology.com) under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Neo Technology licenses this file to you 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 org.neo4j.neoclipse.view;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.neoclipse.Activator;
import org.neo4j.neoclipse.graphdb.GraphCallable;
/**
* Keep track of browsing history and preserve states.
*
* @author Anders Nawroth
*/
public class BrowserHistory
{
/**
* A list of browser states.
*/
private final List<BrowserState> states = new LinkedList<BrowserState>();
/**
* Position of last added item.
*/
private Integer position = null;
/**
* Class to save one browser state.
*/
private static class BrowserState
{
/**
* Id of current node in state.
*/
private final long id;
/**
* Create a state.
*
* @param node the starting point of this state
*/
BrowserState( final Node node )
{
id = node.getId();
}
/**
* Get starting node of this state.
*
* @return starting node or null if it doesn't exist any more
*/
Node getNode()
{
try
{
return Activator.getDefault().getGraphDbServiceManager().submitTask(
new GraphCallable<Node>()
{
public Node call( final GraphDatabaseService graphDb )
{
if ( graphDb != null )
{
try
{
return graphDb.getNodeById( id );
}
catch ( NotFoundException e )
{
return null;
}
}
return null;
}
}, "get starting node of state" ).get();
}
catch ( Exception e )
{
ErrorMessage.showDialog( "Create relationship(s)", e );
}
return null;
}
boolean isWrappingNode( final Node node )
{
return node.getId() == id;
}
@Override
public String toString()
{
return String.valueOf( id );
}
}
/**
* Move backwards in history.
*
* @return previous starting point or null
*/
public Node getPrevious()
{
Node node = null;
while ( node == null && hasPrevious() )
{
--position;
node = fetchPrevious();
}
return node;
}
/**
* Move forward in history.
*
* @return next starting point or null
*/
public Node getNext()
{
Node node = null;
while ( node == null && hasNext() )
{
node = fetchNext();
++position;
}
return node;
}
/**
* Get next node.
*
* @return next node or null
*/
private Node fetchNext()
{
return getNode( position + 1 );
}
/**
* Get previous node.
*
* @return previous node or null
*/
private Node fetchPrevious()
{
return getNode( position );
}
/**
* Get node in list from position.
*
* @param pos position in state list
* @return node at the position or null
*/
private Node getNode( final int pos )
{
return states.get( pos ).getNode();
}
/**
* Check for existence of previous state.
*
* @return true if previous state exist
*/
public boolean hasPrevious()
{
return position != null && position > 0
&& position <= states.size() - 1;
}
/**
* Check for existence of forward state.
*
* @return true if forward state exist
*/
public boolean hasNext()
{
return position != null && position + 1 <= states.size() - 1;
}
/**
* Add a new state.
*
* @param node starting point of state
*/
public void add( final Node node )
{
if ( node == null )
{
throw new IllegalArgumentException(
"Node in history can't be null." );
}
if ( position != null && position < states.size()
&& states.get( position ).isWrappingNode( node ) )
{
return;
}
if ( hasNext() && node.equals( fetchNext() ) )
{
position++;
return;
}
BrowserState state = new BrowserState( node );
// clear rest of list before adding
if ( position == null )
{
position = -1;
}
position++;
if ( states.size() > position && position >= 0 )
{
ListIterator<BrowserState> iter = states.listIterator( position );
while ( iter.hasNext() )
{
iter.next();
iter.remove();
}
position = states.size();
}
states.add( state );
}
public void clear()
{
states.clear();
position = null;
}
}