/**
* 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.kernel;
import org.neo4j.helpers.Service;
/**
* Hook for providing extended functionality to the Neo4j Graph Database kernel.
*
* Implementations of {@link KernelExtension} must fulfill the following
* contract:
* <ul>
* <li>Must have a public no-arg constructor.</li>
* <li>The same instance must be able to load with multiple GraphDatabase
* kernels.</li>
* <li>Different instances should be able to access the same state from the same
* kernel. <br/>
* To achieve this, different instances of the same class should have the same
* {@link #hashCode()} and be {@link #equals(Object)}. This is enforced by this
* base class by delegating {@link #hashCode()} and {@link #equals(Object)} to
* the same methods on the {@link #getClass() class object}.</li>
* </ul>
* The simplest way to implement an {@link KernelExtension extension} that
* fulfills this contract is if the {@link KernelExtension extension}
* implementation is stateless, and all state is kept in the state object
* returned by {@link #load(KernelData) the load method}.
*
* Note that for an {@link KernelExtension extension} to be considered loaded by
* the kernel, {@link #load(KernelData) the load method} may not return
* <code>null</code>. {@link #unload(Object) The unload method} will only be
* invoked if the kernel considers the {@link KernelExtension extension} loaded.
*
* @author Tobias Ivarsson <tobias.ivarsson@neotechnology.com>
* @param <S> the Extension state type
*/
public abstract class KernelExtension<S> extends Service
{
static final String INSTANCE_ID = "instanceId";
public KernelExtension( String key )
{
super( key );
}
@Override
public final int hashCode()
{
return getClass().hashCode();
}
@Override
public final boolean equals( Object obj )
{
return this.getClass().equals( obj.getClass() );
}
public final void loadAgent( String agentArgs )
{
KernelData.visitAll( this, agentArgument( agentArgs ) );
}
protected final void loadAgent( KernelData kernel, Object param )
{
kernel.accept( this, param );
}
protected Object agentArgument( String agentArg )
{
return agentArg;
}
/**
* Load this extension for a particular Neo4j Kernel.
*/
protected abstract S load( KernelData kernel );
protected S agentLoad( KernelData kernel, Object param )
{
S state = load( kernel );
agentVisit( kernel, state, param );
return state;
}
protected void agentVisit( KernelData kernel, S state, Object param )
{
// override to to define behavior
}
/**
* Takes place before any data sources has been registered and is there to
* let extensions affect the configuration of other things starting up.
*/
protected void loadConfiguration( KernelData kernel )
{
// Default: do nothing
}
protected void unload( S state )
{
// Default: do nothing
}
protected final S getState( KernelData kernel )
{
return kernel.getState( this );
}
protected boolean isLoaded( KernelData kernel )
{
return getState( kernel ) != null;
}
}