/*
* 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.kernel;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
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;
import org.neo4j.graphdb.TransactionFailureException;
import org.neo4j.graphdb.event.KernelEventHandler;
import org.neo4j.graphdb.event.TransactionEventHandler;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexProvider;
/**
* An implementation of {@link GraphDatabaseService} that is used to embed Neo4j
* in an application. You typically instantiate it by invoking the
* {@link #EmbeddedGraphDatabase(String) single argument constructor} that takes
* a path to a directory where Neo4j will store its data files, as such:
*
* <pre>
* <code>
* GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "var/graphdb" );
* // ... use Neo4j
* graphDb.shutdown();
* </code>
* </pre>
*
* For more information, see {@link GraphDatabaseService}.
*/
public final class EmbeddedGraphDatabase implements GraphDatabaseService
{
private final EmbeddedGraphDbImpl graphDbImpl;
/**
* Creates an embedded {@link GraphDatabaseService} with a store located in
* <code>storeDir</code>, which will be created if it doesn't already exist.
*
* @param storeDir the store directory for the Neo4j store files
*/
public EmbeddedGraphDatabase( String storeDir )
{
this( storeDir, new HashMap<String, String>() );
}
/**
* A non-standard way of creating an embedded {@link GraphDatabaseService}
* with a set of configuration parameters. Will most likely be removed in
* future releases.
* <p>
* Creates an embedded {@link GraphDatabaseService} with a store located in
* <code>storeDir</code>, which will be created if it doesn't already exist.
*
* @param storeDir the store directory for the db files
* @param params configuration parameters
*/
public EmbeddedGraphDatabase( String storeDir, Map<String,String> params )
{
this.graphDbImpl = new EmbeddedGraphDbImpl( storeDir, params, this );
}
/**
* A non-standard convenience method that loads a standard property file and
* converts it into a generic <Code>Map<String,String></CODE>. Will most
* likely be removed in future releases.
*
* @param file the property file to load
* @return a map containing the properties from the file
* @throws IllegalArgumentException if file does not exist
*/
public static Map<String,String> loadConfigurations( String file )
{
return EmbeddedGraphDbImpl.loadConfigurations( file );
}
public Node createNode()
{
return graphDbImpl.createNode();
}
public Node getNodeById( long id )
{
return graphDbImpl.getNodeById( id );
}
public Relationship getRelationshipById( long id )
{
return graphDbImpl.getRelationshipById( id );
}
public Node getReferenceNode()
{
return graphDbImpl.getReferenceNode();
}
public void shutdown()
{
graphDbImpl.shutdown();
}
public boolean enableRemoteShell()
{
return graphDbImpl.enableRemoteShell();
}
public boolean enableRemoteShell(
final Map<String,Serializable> initialProperties )
{
return graphDbImpl.enableRemoteShell( initialProperties );
}
public Iterable<RelationshipType> getRelationshipTypes()
{
return graphDbImpl.getRelationshipTypes();
}
/**
* @throws TransactionFailureException if unable to start transaction
*/
public Transaction beginTx()
{
return graphDbImpl.beginTx();
}
/**
* Returns a non-standard configuration object. Will most likely be removed
* in future releases.
*
* @return a configuration object
*/
public Config getConfig()
{
return graphDbImpl.getConfig();
}
public <T> T getManagementBean( Class<T> type )
{
return graphDbImpl.getManagementBean( type );
}
@Override
public String toString()
{
return super.toString() + " [" + graphDbImpl.getStoreDir() + "]";
}
public String getStoreDir()
{
return graphDbImpl.getStoreDir();
}
public Iterable<Node> getAllNodes()
{
return graphDbImpl.getAllNodes();
}
public void registerKernelEventHandler(
KernelEventHandler handler )
{
this.graphDbImpl.registerKernelEventHandler( handler );
}
public <T> void registerTransactionEventHandler(
TransactionEventHandler<T> handler )
{
this.graphDbImpl.registerTransactionEventHandler( handler );
}
public void unregisterKernelEventHandler(
KernelEventHandler handler )
{
this.graphDbImpl.unregisterKernelEventHandler( handler );
}
public <T> void unregisterTransactionEventHandler(
TransactionEventHandler<T> handler )
{
this.graphDbImpl.unregisterTransactionEventHandler( handler );
}
public static boolean isReadOnly( GraphDatabaseService graphDb )
{
return graphDb instanceof EmbeddedReadOnlyGraphDatabase;
}
public Index<Node> nodeIndex( String indexName )
{
return this.graphDbImpl.nodeIndex( indexName, null );
}
/**
* Returns an {@link Index} for {@link Node}s by the name {@code name}.
* If that index exists (has been requested before) and the configuration
* was the same as {@code config} it's returned, else if the configuration
* differs an {@link IllegalArgumentException} is thrown. If the index
* doesn't exist it's created with the given configuration. For example:
*
* <code>
* Map<String, String> config = new HashMap<String, String>();
* config.put( "provider", "lucene" );
* config.put( "type", "fulltext" );
* Index<Node> index = embeddedGraphDb.nodeIndex( "users", config );
* ....
* Index<Node> index = embeddedGraphDb.nodeIndex( "users" );
* </code>
*
* Would result in the second call to nodeIndex would return a lucene
* fulltext index for "users".
*
* An index comes from an
* {@link IndexProvider} and which index provider to use is decided via:
*
* <ul>
* <li>Look at stored configuration for the given index</li>
* <li>Look at given configuration map for "provider" key</li>
* <li>Look at configuration parameter
* <b>index.node.[name]</b>, f.ex. <b>index.node.users</b></li>
* <li>Look at configuration parameter <b>index.node</b></li>
* <li>Look at configuration parameter <b>index</b></li>
* <li>Default to lucene index provider</li>
* </ul>
*
* The index provider value can be a class name pointing to an
* {@link IndexProvider} implementation, or a service name specified
* by that provider, f.ex. "lucene". Once an index has be created that same
* index will be returned for the same {@code name}, even if configuration
* changes between runs.
*
* @param name the name of the index to return.
* @return an {@link Index} for {@link Node}s corresponding to the
* {@code name}.
*/
public Index<Node> nodeIndex( String indexName, Map<String, String> config )
{
return this.graphDbImpl.nodeIndex( indexName, config );
}
public Index<Relationship> relationshipIndex( String indexName )
{
return this.graphDbImpl.relationshipIndex( indexName, null );
}
/**
* Returns an {@link Index} for {@link Relationship}s by the name
* {@code name}. If that index exists (has been requested before) and the
* configuration was the same as {@code config} it's returned, else if the
* configuration differs an {@link IllegalArgumentException} is thrown.
* If the index doesn't exist it's created with the given configuration.
* For example:
*
* <code>
* Map<String, String> config = new HashMap<String, String>();
* config.put( "provider", "lucene" );
* config.put( "type", "fulltext" );
* Index<Relationship> index = embeddedGraphDb.nodeIndex( "users", config );
* ....
* Index<Relationship> index = embeddedGraphDb.nodeIndex( "users" );
* </code>
*
* Would result in the second call to nodeIndex would return a lucene
* fulltext index for "users".
*
* An index comes from an
* {@link IndexProvider} and which index provider to use is decided via:
*
* <ul>
* <li>Look at stored configuration for the given index</li>
* <li>Look at given configuration map for "provider" key</li>
* <li>Look at configuration parameter
* <b>index.relationship.[name]</b>, f.ex.
* <b>index.relationship.users</b></li>
* <li>Look at configuration parameter <b>index.relationship</b></li>
* <li>Look at configuration parameter <b>index</b></li>
* <li>Default to lucene index provider</li>
* </ul>
*
* The index provider value can be a class name pointing to an
* {@link IndexProvider} implementation, or a service name specified
* by that provider, f.ex. "lucene". Once an index has be created that same
* index will be returned for the same {@code name}, even if configuration
* changes between runs.
*
* @param name the name of the index to return.
* @return an {@link Index} for {@link Relationship}s corresponding to the
* {@code name}.
*/
public Index<Relationship> relationshipIndex( String indexName, Map<String, String> config )
{
return this.graphDbImpl.relationshipIndex( indexName, config );
}
}