package er.neo4jadaptor.database.pool;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import er.extensions.foundation.ERXProperties;
/**
* Responsible for providing the right database type for a given label.
*
* @see DatabaseFactoryTypeLabels
*
* @author Jedrzej Sobanski
*/
public enum DatabaseFactoryType {
/**
* Embedded database running in read-only mode (useful when the db is locked by another instance running in writable mode and locking database).
*/
EMBEDDED_READ_ONLY(DatabaseFactoryTypeLabels.LABEL_EMBEDDED_READ_ONLY, new Neo4JDatabaseFactory() {
public GraphDatabaseService get(String path, Map<String, String> config) {
log.info("Creating Neo4J embedded read-only database instance with config {} in {}.", config, path);
return new EmbeddedReadOnlyGraphDatabase(path, config);
}
}),
/**
* Embedded database running in writable mode.
*/
EMBEDDED_WRITABLE(DatabaseFactoryTypeLabels.LABEL_EMBEDDED_WRITABLE, new Neo4JDatabaseFactory() {
public GraphDatabaseService get(String path, Map<String, String> config) {
log.info("Creating Neo4J embedded writable database instance with config {} in {}.", config, path);
return new EmbeddedGraphDatabase(path, config);
}
}),
/**
* Highly available database.
*
* <div><b>Requires Neo4J enterprise edition.</b></div>
*/
HIGHLY_AVAILABLE(DatabaseFactoryTypeLabels.LABEL_HIGHLY_AVAILABLE, new Neo4JDatabaseFactory() {
public GraphDatabaseService get(String path, Map<String, String> config) {
log.info("Creating Neo4J highly-available database instance with config {} in {}.", config, path);
try {
Constructor<? extends GraphDatabaseService> constructor = haConstructor();
String serverId = config.get(HA_SERVER_ID_KEY);
String fullPath = path + "-" + serverId;
return constructor.newInstance(fullPath, config);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private Constructor<? extends GraphDatabaseService> haConstructor() throws SecurityException, NoSuchMethodException, ClassNotFoundException {
Class<? extends GraphDatabaseService> haClass = (Class<? extends GraphDatabaseService>) Class.forName(HA_CLASS_NAME);
return haClass.getConstructor(String.class, Map.class);
}
});
private static final Logger log = LoggerFactory.getLogger(DatabaseFactoryType.class);
private static final String HA_SERVER_ID_KEY = ERXProperties.stringForKey("neo4j.pool.database.highly-available.server-id-config-key");
private static final String HA_CLASS_NAME = ERXProperties.stringForKey("neo4j.pool.database.highly-available.class");
private final String label;
private final Neo4JDatabaseFactory factory;
private DatabaseFactoryType(String label, Neo4JDatabaseFactory factory) {
this.label = label;
this.factory = factory;
}
/**
* Gets factory type for the given type label.
*
* @param label
* @return factory type
*/
public static DatabaseFactoryType getForLabel(String label) {
for (DatabaseFactoryType df : values()) {
if (label.equals(df.label)) {
return df;
}
}
return null;
}
public Neo4JDatabaseFactory getFactory() {
return factory;
}
}