package com.tinkerpop.frames;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler;
import com.tinkerpop.frames.annotations.DomainAnnotationHandler;
import com.tinkerpop.frames.annotations.IncidenceAnnotationHandler;
import com.tinkerpop.frames.annotations.InVertexAnnotationHandler;
import com.tinkerpop.frames.annotations.PropertyAnnotationHandler;
import com.tinkerpop.frames.annotations.RangeAnnotationHandler;
import com.tinkerpop.frames.annotations.OutVertexAnnotationHandler;
import com.tinkerpop.frames.modules.Module;
/**
* Creates a factory for creating {@link FramedGraph}s using a set of modules to
* configure each graph. Note that by default all Framed graphs have the
* following handlers registered: {@link PropertyAnnotationHandler}
* {@link AdjacencyAnnotationHandler} {@link IncidenceAnnotationHandler}
* {@link DomainAnnotationHandler} {@link RangeAnnotationHandler}
*
* @author Bryn Cooke
*
*/
public class FramedGraphFactory {
private Module[] modules;
/**
* Create a {@link FramedGraphFactory} with a set of modules.
*
* @param modules
* The modules used to configure each {@link FramedGraph} created
* by the factory.
*/
public FramedGraphFactory(Module... modules) {
this.modules = modules;
}
/**
* Create a new {@link FramedGraph}.
*
* @param baseGraph
* The graph whose elements to frame.
* @return The {@link FramedGraph}
*/
public <T extends Graph> FramedGraph<T> create(T baseGraph) {
FramedGraphConfiguration config = getConfiguration(Graph.class, baseGraph);
FramedGraph<T> framedGraph = new FramedGraph<T>(baseGraph, config);
return framedGraph;
}
/**
* Create a new {@link FramedGraph}.
*
* @param baseGraph
* The graph whose elements to frame.
* @return The {@link FramedGraph}
*/
public <T extends TransactionalGraph> FramedTransactionalGraph<T> create(T baseGraph) {
FramedGraphConfiguration config = getConfiguration(TransactionalGraph.class, baseGraph);
FramedTransactionalGraph<T> framedGraph = new FramedTransactionalGraph<T>(baseGraph, config);
return framedGraph;
}
/**
* Returns a configuration that can be used when constructing a framed graph.
* @param requiredType The type of graph required after configuration e.g. {@link TransactionalGraph}
* @param baseGraph The base graph to get a configuration for.
* @return The configuration.
*/
protected <T extends Graph> FramedGraphConfiguration getConfiguration(Class<T> requiredType, T baseGraph) {
Graph configuredGraph = baseGraph;
FramedGraphConfiguration config = getBaseConfig();
for (Module module : modules) {
configuredGraph = module.configure(configuredGraph, config);
if(!(requiredType.isInstance(configuredGraph))) {
throw new UnsupportedOperationException("Module '" + module.getClass() + "' returned a '" + baseGraph.getClass().getName() + "' but factory requires '" + requiredType.getName() + "'");
}
}
config.setConfiguredGraph(configuredGraph);
return config;
}
private FramedGraphConfiguration getBaseConfig() {
FramedGraphConfiguration config = new FramedGraphConfiguration();
config.addAnnotationHandler(new PropertyAnnotationHandler());
config.addAnnotationHandler(new AdjacencyAnnotationHandler());
config.addAnnotationHandler(new IncidenceAnnotationHandler());
config.addAnnotationHandler(new DomainAnnotationHandler());
config.addAnnotationHandler(new RangeAnnotationHandler());
config.addAnnotationHandler(new InVertexAnnotationHandler());
config.addAnnotationHandler(new OutVertexAnnotationHandler());
return config;
}
}