/**
* 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.shell.kernel;
import java.io.Serializable;
import java.util.Map;
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.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.graphdb.event.KernelEventHandler;
import org.neo4j.graphdb.event.TransactionEventHandler;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.kernel.impl.traversal.OldTraverserWrapper;
public class ReadOnlyGraphDatabaseProxy implements GraphDatabaseService
{
private final GraphDatabaseService actual;
ReadOnlyGraphDatabaseProxy( GraphDatabaseService graphDb )
{
this.actual = graphDb;
}
public GraphDatabaseService getActualGraphDb()
{
return actual;
}
public Node readOnly( Node actual )
{
return new ReadOnlyNodeProxy( actual );
}
public Relationship readOnly( Relationship actual )
{
return new ReadOnlyRelationshipProxy( actual );
}
private static <T> T readOnly()
{
throw new UnsupportedOperationException( "Read only Graph Database!" );
}
public Transaction beginTx()
{
// return readOnly();
return new Transaction()
{
public void success()
{
}
public void failure()
{
}
public void finish()
{
}
};
}
public Node createNode()
{
return readOnly();
}
public boolean enableRemoteShell()
{
throw new UnsupportedOperationException( "Cannot enable Remote Shell from Remote Shell" );
}
public boolean enableRemoteShell( Map<String, Serializable> initialProperties )
{
return enableRemoteShell();
}
public Iterable<Node> getAllNodes()
{
return nodes( actual.getAllNodes() );
}
public Node getNodeById( long id )
{
return new ReadOnlyNodeProxy( actual.getNodeById( id ) );
}
public Node getReferenceNode()
{
return new ReadOnlyNodeProxy( actual.getReferenceNode() );
}
public Relationship getRelationshipById( long id )
{
return new ReadOnlyRelationshipProxy( actual.getRelationshipById( id ) );
}
public Iterable<RelationshipType> getRelationshipTypes()
{
return actual.getRelationshipTypes();
}
public KernelEventHandler registerKernelEventHandler( KernelEventHandler handler )
{
return readOnly();
}
public <T> TransactionEventHandler<T> registerTransactionEventHandler(
TransactionEventHandler<T> handler )
{
return readOnly();
}
public void shutdown()
{
actual.shutdown();
}
public KernelEventHandler unregisterKernelEventHandler( KernelEventHandler handler )
{
return readOnly();
}
public <T> TransactionEventHandler<T> unregisterTransactionEventHandler(
TransactionEventHandler<T> handler )
{
return readOnly();
}
private class ReadOnlyNodeProxy implements Node
{
private final Node actual;
ReadOnlyNodeProxy( Node actual )
{
this.actual = actual;
}
@Override
public int hashCode()
{
return actual.hashCode();
}
@Override
public boolean equals( Object obj )
{
return ( obj instanceof Node ) && ( (Node) obj ).getId() == getId();
}
@Override
public String toString()
{
return actual.toString();
}
public long getId()
{
return actual.getId();
}
public Relationship createRelationshipTo( Node otherNode, RelationshipType type )
{
return readOnly();
}
public void delete()
{
readOnly();
}
public Iterable<Relationship> getRelationships()
{
return relationships( actual.getRelationships() );
}
public Iterable<Relationship> getRelationships( RelationshipType... types )
{
return relationships( actual.getRelationships( types ) );
}
public Iterable<Relationship> getRelationships( Direction dir )
{
return relationships( actual.getRelationships( dir ) );
}
public Iterable<Relationship> getRelationships( RelationshipType type, Direction dir )
{
return relationships( actual.getRelationships( type, dir ) );
}
public Relationship getSingleRelationship( RelationshipType type, Direction dir )
{
return new ReadOnlyRelationshipProxy( actual.getSingleRelationship( type, dir ) );
}
public boolean hasRelationship()
{
return actual.hasRelationship();
}
public boolean hasRelationship( RelationshipType... types )
{
return actual.hasRelationship( types );
}
public boolean hasRelationship( Direction dir )
{
return actual.hasRelationship( dir );
}
public boolean hasRelationship( RelationshipType type, Direction dir )
{
return actual.hasRelationship( type, dir );
}
public Traverser traverse( Order traversalOrder, StopEvaluator stopEvaluator,
ReturnableEvaluator returnableEvaluator, RelationshipType relationshipType,
Direction direction )
{
return OldTraverserWrapper.traverse( this, traversalOrder, stopEvaluator,
returnableEvaluator, relationshipType, direction );
}
public Traverser traverse( Order traversalOrder, StopEvaluator stopEvaluator,
ReturnableEvaluator returnableEvaluator, RelationshipType firstRelationshipType,
Direction firstDirection, RelationshipType secondRelationshipType,
Direction secondDirection )
{
return OldTraverserWrapper.traverse( this, traversalOrder, stopEvaluator,
returnableEvaluator, firstRelationshipType, firstDirection,
secondRelationshipType, secondDirection );
}
public Traverser traverse( Order traversalOrder, StopEvaluator stopEvaluator,
ReturnableEvaluator returnableEvaluator, Object... relationshipTypesAndDirections )
{
return OldTraverserWrapper.traverse( this, traversalOrder, stopEvaluator,
returnableEvaluator, relationshipTypesAndDirections );
}
public GraphDatabaseService getGraphDatabase()
{
return ReadOnlyGraphDatabaseProxy.this;
}
public Object getProperty( String key )
{
return actual.getProperty( key );
}
public Object getProperty( String key, Object defaultValue )
{
return actual.getProperty( key, defaultValue );
}
public Iterable<String> getPropertyKeys()
{
return actual.getPropertyKeys();
}
public Iterable<Object> getPropertyValues()
{
return actual.getPropertyValues();
}
public boolean hasProperty( String key )
{
return actual.hasProperty( key );
}
public Object removeProperty( String key )
{
return readOnly();
}
public void setProperty( String key, Object value )
{
readOnly();
}
}
private class ReadOnlyRelationshipProxy implements Relationship
{
private final Relationship actual;
ReadOnlyRelationshipProxy( Relationship actual )
{
this.actual = actual;
}
@Override
public int hashCode()
{
return actual.hashCode();
}
@Override
public boolean equals( Object obj )
{
return ( obj instanceof Relationship ) && ( (Relationship) obj ).getId() == getId();
}
@Override
public String toString()
{
return actual.toString();
}
public long getId()
{
return actual.getId();
}
public void delete()
{
readOnly();
}
public Node getEndNode()
{
return new ReadOnlyNodeProxy( actual.getEndNode() );
}
public Node[] getNodes()
{
return new Node[] { getStartNode(), getEndNode() };
}
public Node getOtherNode( Node node )
{
return new ReadOnlyNodeProxy( actual.getOtherNode( node ) );
}
public Node getStartNode()
{
return new ReadOnlyNodeProxy( actual.getStartNode() );
}
public RelationshipType getType()
{
return actual.getType();
}
public boolean isType( RelationshipType type )
{
return actual.isType( type );
}
public GraphDatabaseService getGraphDatabase()
{
return ReadOnlyGraphDatabaseProxy.this;
}
public Object getProperty( String key )
{
return actual.getProperty( key );
}
public Object getProperty( String key, Object defaultValue )
{
return actual.getProperty( key, defaultValue );
}
public Iterable<String> getPropertyKeys()
{
return actual.getPropertyKeys();
}
public Iterable<Object> getPropertyValues()
{
return actual.getPropertyValues();
}
public boolean hasProperty( String key )
{
return actual.hasProperty( key );
}
public Object removeProperty( String key )
{
return readOnly();
}
public void setProperty( String key, Object value )
{
readOnly();
}
}
public Iterable<Node> nodes( Iterable<Node> nodes )
{
return new IterableWrapper<Node, Node>( nodes )
{
@Override
protected Node underlyingObjectToObject( Node node )
{
return new ReadOnlyNodeProxy( node );
}
};
}
public Iterable<Relationship> relationships( Iterable<Relationship> relationships )
{
return new IterableWrapper<Relationship, Relationship>( relationships )
{
@Override
protected Relationship underlyingObjectToObject( Relationship relationship )
{
return new ReadOnlyRelationshipProxy( relationship );
}
};
}
}