package fr.inria.atlanmod.neo4emf.drivers.tests;
import static org.junit.Assert.fail;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClassifier;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.index.lucene.LuceneKernelExtensionFactory;
import org.neo4j.kernel.extension.KernelExtensionFactory;
import org.neo4j.kernel.impl.cache.CacheProvider;
import org.neo4j.kernel.impl.cache.SoftCacheProvider;
import fr.inria.atlanmod.neo4emf.INeo4emfObject;
import fr.inria.atlanmod.neo4emf.drivers.IPersistenceService;
import fr.inria.atlanmod.neo4emf.drivers.NEConfiguration;
import fr.inria.atlanmod.neo4emf.drivers.NEConnection;
import fr.inria.atlanmod.neo4emf.drivers.impl.NETransaction;
import fr.inria.atlanmod.neo4emf.testdata.Temperature;
import fr.inria.atlanmod.neo4emf.testdata.TestFactory;
import fr.inria.atlanmod.neo4emf.testdata.TestPackage;
import fr.inria.atlanmod.neo4emf.testdata.Vertex;
public class NEConnectionTest {
private GraphDatabaseService db;
private NEConnection connection;
private static final File DB_FOLDER = new File("/tmp/NEConnectionTest/");
private static final URI uri = URI.createURI("neo4emf:"
+ DB_FOLDER.getAbsolutePath());
private static GraphDatabaseFactory gdbf;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
FileUtils.forceMkdir(DB_FOLDER);
// the cache providers
List<CacheProvider> cacheList = new ArrayList<CacheProvider>();
cacheList.add(new SoftCacheProvider());
// the kernel extensions
LuceneKernelExtensionFactory lucene = new LuceneKernelExtensionFactory();
List<KernelExtensionFactory<?>> extensions = new ArrayList<KernelExtensionFactory<?>>();
extensions.add(lucene);
// the database setup
gdbf = new GraphDatabaseFactory();
gdbf.setKernelExtensions(extensions);
gdbf.setCacheProviders(cacheList);
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
FileUtils.forceDelete(DB_FOLDER);
}
@Before
public void setUp() throws Exception {
db = gdbf.newEmbeddedDatabase(DB_FOLDER.getAbsolutePath());
registerShutdownHook(db);
NEConfiguration conf = new NEConfiguration(TestPackage.eINSTANCE, uri,
Collections.<String, String> emptyMap());
connection = new NEConnection(db, conf);
connection.open();
}
@After
public void tearDown() throws Exception {
connection.close();
}
@Test
public void testOpen() {
IndexManager im = db.index();
assert im.existsForNodes(IPersistenceService.META_ELEMENTS) : "Meta index not created";
Index<Node> index = im.forNodes(IPersistenceService.META_ELEMENTS);
for (EClassifier each : TestPackage.eINSTANCE.getEClassifiers()) {
String id = each.getEPackage().getName() + "_"
+ each.getClassifierID();
Node n = index.get(IPersistenceService.ID_META, id).getSingle();
// System.out.println(n.getProperty(IPersistenceService.ECLASS_NAME));
assert n != null : "Missing Node for Eclass";
}
}
@Test
public void testAddNode() {
TestFactory factory = TestFactory.eINSTANCE;
Vertex v = factory.createVertex();
NETransaction tx = connection.createTransaction();
try {
Node n = connection.addObject(v);
assert n.getId() == v.getNodeId() : "Wrong node id";
tx.success();
} catch (Exception e) {
tx.abort();
} finally {
tx.commit();
// connection.close();
}
}
@Test
public void testAddRootObject() {
TestFactory factory = TestFactory.eINSTANCE;
Vertex v = factory.createVertex();
NETransaction tx = connection.createTransaction();
try {
assert connection.addRootObject(v,true) != null : "Root object not added.";
Iterable<Relationship> rels = this.resourceNode().getRelationships(IPersistenceService.IS_ROOT);
Node newNode = db.getNodeById(v.getNodeId());
boolean found = false;
for(Relationship each : rels) {
if (each.getEndNode().getId() == newNode.getId()) {
found = true;
break;
}
}
assert found : "Node node found";
tx.success();
} catch (Exception e) {
tx.abort();
} finally {
tx.commit();
// connection.close();
}
}
/**
* Asserts that attributes are correctly saved as node properties.
*/
@Test
public void testSaveObjectProperties() {
String name = "My Object Special Name";
Temperature temperature = Temperature.HOT;
BigDecimal decimal = BigDecimal.valueOf(1000.09);
BigInteger integer = BigInteger.valueOf(42);
boolean[] booleanArray = {true, true, false, false, true, false};
String[] stringArray = {"My", "very", "complex", "string","array"};
double[] doubleArray = {1.2, 3.4, 999999.27, 4444.42};
long[] longArray = {1,2,3,6,Long.MAX_VALUE, Long.MIN_VALUE};
TestFactory factory = TestFactory.eINSTANCE;
Vertex v = factory.createVertex();
NETransaction tx = connection.createTransaction();
try {
Node n = connection.addObject(v);
v.setABoolean(true);
v.setName(name);
v.setTemperature(Temperature.HOT);
v.setAReal(decimal);
v.setATransientInteger(integer);
for (boolean each : booleanArray) {
v.getANonOrderedArray().add(each);
}
for(String each : stringArray) {
v.getAStringArray().add(each);
}
for(double each : doubleArray) {
v.getANonUniqueArray().add(BigDecimal.valueOf(each));
}
for(long each : longArray) {
v.getAnIntegerArray().add(BigInteger.valueOf(each));
}
connection.saveAllAttributes(v);
assert (boolean) n.getProperty("aBoolean") : "Wrong boolean";
assert temperature == Temperature.get((int) n.getProperty("temperature")) : "Wrong enumeration value";
assert name.equals(n.getProperty("name")) : "Wrong String";
assert decimal.doubleValue() == (double) n.getProperty("aReal") : "Wrong Real";
assert integer.longValue() == (long) n.getProperty("aTransientInteger") : "Wrong Integer";
boolean[] resultArray = (boolean[]) n.getProperty("aNonOrderedArray");
assert Arrays.equals(booleanArray, resultArray) : "Wrong Array Value" ;
String[] resultStringArray = (String[]) n.getProperty("aStringArray");
assert Arrays.equals(stringArray, resultStringArray) : "Wrong String Array Value";
double[] resultDecimalArray = (double[]) n.getProperty("aNonUniqueArray");
assert Arrays.equals(doubleArray, resultDecimalArray) : "Wrong Double Array Value";
long[] resultLongArray = (long[]) n.getProperty("anIntegerArray");
assert Arrays.equals(longArray,resultLongArray);
tx.success();
} catch (Exception e) {
e.printStackTrace();
fail("Something went wrong during database transaction");
tx.abort();
} finally {
tx.commit();
// connection.close();
}
}
@Test
public void testRetrieveObject() {
String name = "Vertex Name";
TestFactory factory = TestFactory.eINSTANCE;
Vertex v = factory.createVertex();
v.setName(name);
NETransaction tx = connection.createTransaction();
try {
Node n = connection.addObject(v);
connection.saveAllAttributes(v);
Vertex retrieved = (Vertex) connection.retrieveObject(n.getId());
connection.loadAttributes(retrieved);
assert retrieved.getNodeId() == v.getNodeId() : "Wrong node id";
assert retrieved.eClass() == v.eClass() : "Wrong Type (EClass)";
assert name.equals(retrieved.getName());
tx.success();
} catch (Exception e) {
e.printStackTrace();
fail("Something went wrong during database transaction");
tx.abort();
} finally {
tx.commit();
// connection.close();
}
}
@Test
public void testRetrieveCachedObject() {
String name = "Vertex Name";
TestFactory factory = TestFactory.eINSTANCE;
Vertex v = factory.createVertex();
v.setName(name);
NETransaction tx = connection.createTransaction();
try {
Node n = connection.addObject(v);
connection.saveAllAttributes(v);
Vertex first = (Vertex) connection.retrieveObject(n.getId());
Vertex second = (Vertex) connection.retrieveObject(n.getId());
connection.loadAttributes(first);
assert first == second : "Object created twice";
tx.success();
} catch (Exception e) {
e.printStackTrace();
fail("Something went wrong during database transaction");
tx.abort();
} finally {
tx.commit();
// connection.close();
}
}
private Node resourceNode() {
IndexManager manager = db.index();
Index<Node> metaIndex = manager.forNodes(IPersistenceService.META_ELEMENTS);
Node resourceNode = metaIndex.get(IPersistenceService.ID_META,
IPersistenceService.RESOURCE_NODE).getSingle();
return resourceNode;
}
private static void registerShutdownHook(final GraphDatabaseService graphDb) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// At this point the plugin "Neo4emfPlugin" has been already
// stopped
// Don't use the shared instance!
// Shutdown the DB
graphDb.shutdown();
}
});
}
}