/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.CommandsFactory;
import org.jboss.cache.factories.ComponentFactory;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.invocation.NodeInvocationDelegate;
import org.jboss.cache.lock.LockStrategyFactory;
import org.jboss.cache.optimistic.TransactionWorkspace;
import org.jboss.cache.optimistic.WorkspaceNode;
import org.jboss.cache.optimistic.WorkspaceNodeImpl;
import java.util.Map;
/**
* Generates new nodes based on the {@link CacheSPI} configuration.
*
* @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
*/
public class NodeFactory<K, V> extends ComponentFactory
{
private CacheSPI<K, V> cache;
private boolean optimistic;
private Configuration configuration;
private InvocationContextContainer invocationContextContainer;
private InterceptorChain interceptorChain;
private CommandsFactory commandsFactory;
private LockStrategyFactory lockStrategyFactory;
@Override
protected <T> T construct(Class<T> componentType)
{
throw new UnsupportedOperationException("Should never be called!");
}
public static enum NodeType
{
UNVERSIONED_NODE, VERSIONED_NODE, WORKSPACE_NODE
}
/**
* Constructs an instance of the factory
*/
public NodeFactory(CacheSPI<K, V> cache)
{
this.cache = cache;
init();
}
public NodeFactory()
{
}
@Inject
private void injectDependencies(CacheSPI<K, V> cache, Configuration configuration,
InvocationContextContainer invocationContextContainer,
InterceptorChain interceptorChain, CommandsFactory commandsFactory, LockStrategyFactory lockStrategyFactory)
{
this.cache = cache;
this.configuration = configuration;
this.invocationContextContainer = invocationContextContainer;
this.interceptorChain = interceptorChain;
this.commandsFactory = commandsFactory;
this.lockStrategyFactory = lockStrategyFactory;
}
/**
* Initialises the node factory with the configuration from the cache.
*/
@Start
public void init()
{
optimistic = configuration.isNodeLockingOptimistic();
}
/**
* Creates a new {@link Node} instance.
*
* @param childName the new node's name
* @param fqn the new node's Fqn
* @param parent the new node's parent
* @param data the new node's attribute map
* @param mapSafe <code>true</code> if param <code>data</code> can safely
* be directly assigned to the new node's data field;
* <code>false</code> if param <code>data</code>'s contents
* should be copied into the new node's data field.
* @return the new node
*/
public NodeSPI<K, V> createDataNode(Object childName, Fqn fqn, NodeSPI<K, V> parent, Map<K, V> data, boolean mapSafe)
{
UnversionedNode un = optimistic ? new VersionedNode<K, V>(fqn, parent, data, cache) : new UnversionedNode<K, V>(childName, fqn, data, mapSafe, cache);
// always assume that new nodes do not have data loaded
un.setDataLoaded(false);
NodeInvocationDelegate<K, V> nid = new NodeInvocationDelegate(un);
// Too slow to have these autowired for now. Look at manually wiring them.
nid.initialize(configuration, invocationContextContainer, componentRegistry, interceptorChain);
nid.injectDependencies(cache);
un.injectDependencies(cache, commandsFactory, lockStrategyFactory);
// componentRegistry.wireDependencies(nid);
// componentRegistry.wireDependencies(un);
// back ref
un.setDelegate(nid);
return nid;
}
public Node<K, V> createNode(Object childName, Node<K, V> parent, Map<K, V> data)
{
return createNodeOfType(parent, childName, parent, data);
}
public Node<K, V> createNodeOfType(Node<K, V> template, Object childName, Node<K, V> parent, Map<K, V> data)
{
// not a workspace node.
return createDataNode(childName, Fqn.fromRelativeElements(parent.getFqn(), childName), (NodeSPI<K, V>) parent, data, false);
}
public WorkspaceNode<K, V> createWorkspaceNode(NodeSPI<K, V> dataNode, TransactionWorkspace workspace)
{
return new WorkspaceNodeImpl<K, V>(dataNode, workspace);
}
public NodeSPI<K, V> createRootDataNode()
{
return createDataNode(null, Fqn.ROOT, null, null, false);
}
}