package org.orienteer.core; import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.inject.Provider; import org.junit.Test; import org.junit.runner.RunWith; import org.orienteer.core.CustomAttribute; import org.orienteer.core.hook.CallbackHook; import org.orienteer.junit.OrienteerTestRunner; import static org.junit.Assert.*; import ru.ydn.wicket.wicketorientdb.OrientDbWebSession; import com.google.inject.Inject; import com.google.inject.Singleton; import com.orientechnologies.orient.core.db.document.ODatabaseDocument; import com.orientechnologies.orient.core.db.record.OIdentifiable; import com.orientechnologies.orient.core.hook.ORecordHook.TYPE; import com.orientechnologies.orient.core.metadata.schema.OClass; import com.orientechnologies.orient.core.metadata.schema.OProperty; import com.orientechnologies.orient.core.metadata.schema.OSchema; import com.orientechnologies.orient.core.metadata.schema.OType; import com.orientechnologies.orient.core.record.impl.ODocument; @RunWith(OrienteerTestRunner.class) @Singleton public class HooksTest { private static final String TEST_CLASS_A = "TestClassA"; private static final String TEST_CLASS_B = "TestClassB"; private static final String TEST_CLASS_C = "TestClassC"; private static final String TEST_CLASS_CALLBACK = "TestClassCallbacks"; @Test public void testCalculableHook() throws Exception { assertTrue(OrientDbWebSession.get().signIn("admin", "admin")); ODatabaseDocument db = OrientDbWebSession.get().getDatabase(); OSchema schema = db.getMetadata().getSchema(); assertFalse(db.isClosed()); db.commit(); if(schema.existsClass(TEST_CLASS_A)) schema.dropClass(TEST_CLASS_A); OClass oClass = schema.createClass(TEST_CLASS_A); try { oClass.createProperty("a", OType.INTEGER); oClass.createProperty("b", OType.INTEGER); OProperty cProperty = oClass.createProperty("c", OType.INTEGER); OProperty dProperty = oClass.createProperty("d", OType.INTEGER); CustomAttribute.CALCULABLE.setValue(cProperty, true); CustomAttribute.CALCULABLE.setValue(dProperty, true); CustomAttribute.CALC_SCRIPT.setValue(cProperty, "select sum(a, b) as value from TestClassA where @rid = ?"); CustomAttribute.CALC_SCRIPT.setValue(dProperty, "sum(a, b)"); ODocument doc = new ODocument(oClass); doc.field("a", 2); doc.field("b", 2); doc.save(); doc.reload(); assertEquals(4, doc.field("c")); assertEquals(4, doc.field("d")); doc.field("a", 3); doc.field("b", 3); doc.save(); doc.reload(); assertEquals(6, doc.field("c")); assertEquals(6, doc.field("d")); db.begin(); doc.field("a", 4); doc.field("b", 4); doc.save(); doc.reload(); assertEquals(8, doc.field("c")); assertEquals(8, doc.field("d")); db.commit(); db.begin(); doc.field("a", 5); doc.field("b", 5); doc.save(); doc.reload(); assertEquals(10, doc.field("c")); assertEquals(10, doc.field("d")); db.commit(); } finally { if(db.getTransaction().isActive()) db.commit(); schema.dropClass(TEST_CLASS_A); OrientDbWebSession.get().signOut(); } } @Test public void testReferencesHook() throws Exception { assertTrue(OrientDbWebSession.get().signIn("admin", "admin")); ODatabaseDocument db = OrientDbWebSession.get().getDatabase(); OSchema schema = db.getMetadata().getSchema(); assertFalse(db.isClosed()); db.commit(); if(schema.existsClass(TEST_CLASS_B)) schema.dropClass(TEST_CLASS_B); OClass classB = schema.createClass(TEST_CLASS_B); try { OProperty parent = classB.createProperty("parent", OType.LINK); OProperty child = classB.createProperty("child", OType.LINKLIST); CustomAttribute.PROP_INVERSE.setValue(parent, child); CustomAttribute.PROP_INVERSE.setValue(child, parent); //Create root object ODocument rootDoc = new ODocument(classB); rootDoc.save(); //Create first child ODocument child1Doc = new ODocument(classB); child1Doc.field("parent", rootDoc); child1Doc.save(); //Check that back ref is here rootDoc.reload(); Collection<OIdentifiable> childCollection = rootDoc.field("child"); assertEquals(1, childCollection.size()); assertTrue(childCollection.contains(child1Doc)); //Create second child ODocument child2Doc = new ODocument(classB); child2Doc.field("parent", rootDoc); child2Doc.save(); //Check that back ref to 2 child doc here rootDoc.reload(); childCollection = rootDoc.field("child"); assertEquals(2, childCollection.size()); assertTrue(childCollection.contains(child1Doc)); assertTrue(childCollection.contains(child2Doc)); //Remove first child; child1Doc.reload(); child1Doc.delete(); //Check that back ref to second child doc here rootDoc.reload(); childCollection = rootDoc.field("child"); assertEquals(1, childCollection.size()); assertTrue(childCollection.contains(child2Doc)); //Create 3rd child ODocument child3Doc = new ODocument(classB); child3Doc.save(); //Associate 3rd child with root by attribute childCollection.add(child3Doc); rootDoc.field("child", childCollection); rootDoc.save(); //Check that association is correct for root rootDoc.reload(); childCollection = rootDoc.field("child"); assertEquals(2, childCollection.size()); assertTrue(childCollection.contains(child2Doc)); assertTrue(childCollection.contains(child3Doc)); //Check that association is correct for child3 child3Doc.reload(); assertNotNull("Parent should be set", child3Doc.field("parent")); OIdentifiable rootId = child3Doc.field("parent"); assertEquals(rootDoc, rootId.getRecord()); //Now lets update parent for child2 to null child2Doc.field("parent", (Object)null); child2Doc.save(); //Check root rootDoc.reload(); childCollection = rootDoc.field("child"); assertEquals(1, childCollection.size()); assertTrue(childCollection.contains(child3Doc)); //Lets delete reference to child3 by clear childCollection.clear(); // childCollection.remove(child3Doc); rootDoc.field("child", childCollection); rootDoc.save(); //Check back ref from Child3 child3Doc.reload(); assertNull(child3Doc.field("parent")); //Lets create one more Root to test setting collection from scratch ODocument root2Doc = new ODocument(classB); root2Doc.save(); ODocument childTestForNull = new ODocument(classB); childTestForNull.save(); assertNull(root2Doc.field("child")); root2Doc.field("child", Arrays.asList(childTestForNull)); root2Doc.save(); childTestForNull.reload(); childCollection = root2Doc.field("child"); assertEquals(1, childCollection.size()); assertTrue(childCollection.contains(childTestForNull)); assertEquals(root2Doc, childTestForNull.field("parent")); } finally { schema.dropClass(TEST_CLASS_B); OrientDbWebSession.get().signOut(); } } @Test public void testReferencesHookDeepCase() throws Exception { assertTrue(OrientDbWebSession.get().signIn("admin", "admin")); ODatabaseDocument db = OrientDbWebSession.get().getDatabase(); OSchema schema = db.getMetadata().getSchema(); assertFalse(db.isClosed()); db.commit(); if(schema.existsClass(TEST_CLASS_C)) schema.dropClass(TEST_CLASS_C); OClass classC = schema.createClass(TEST_CLASS_C); try { OProperty parent = classC.createProperty("parent", OType.LINK); OProperty child = classC.createProperty("child", OType.LINKLIST); CustomAttribute.PROP_INVERSE.setValue(parent, child); CustomAttribute.PROP_INVERSE.setValue(child, parent); ODocument doc1 = new ODocument(classC).save(); ODocument doc2 = new ODocument(classC).save(); ODocument doc3 = new ODocument(classC).save(); doc1.field("child", Arrays.asList(doc2)); doc1.save(); doc2.reload(); assertEquals(doc1, doc2.field("parent")); doc3.field("child", Arrays.asList(doc2)); doc3.save(); doc2.reload(); assertEquals(doc3, doc2.field("parent")); doc1.reload(); List<ODocument> childs = doc1.field("child"); assertNotNull(childs); assertArrayEquals(new ODocument[0], childs.toArray(new ODocument[0])); } finally { schema.dropClass(TEST_CLASS_C); OrientDbWebSession.get().signOut(); } } @Test public void testReferencesHookChangeParent() throws Exception { assertTrue(OrientDbWebSession.get().signIn("admin", "admin")); ODatabaseDocument db = OrientDbWebSession.get().getDatabase(); OSchema schema = db.getMetadata().getSchema(); assertFalse(db.isClosed()); db.commit(); if(schema.existsClass(TEST_CLASS_C)) schema.dropClass(TEST_CLASS_C); OClass classC = schema.createClass(TEST_CLASS_C); try { OProperty parent = classC.createProperty("parent", OType.LINK); OProperty child = classC.createProperty("child", OType.LINKLIST); CustomAttribute.PROP_INVERSE.setValue(parent, child); CustomAttribute.PROP_INVERSE.setValue(child, parent); ODocument doc1 = new ODocument(classC).save(); ODocument doc2 = new ODocument(classC).save(); ODocument doc3 = new ODocument(classC).save(); doc1.field("child", Arrays.asList(doc2)); doc1.save(); doc2.reload(); assertEquals(doc1, doc2.field("parent")); doc2.field("parent", doc3); doc2.save(); doc1.reload(); doc3.reload(); List<ODocument> childs = doc1.field("child"); assertNotNull(childs); assertArrayEquals(new ODocument[0], childs.toArray(new ODocument[0])); childs = doc3.field("child"); assertNotNull(childs); assertArrayEquals(new ODocument[]{doc2}, childs.toArray(new ODocument[0])); } finally { schema.dropClass(TEST_CLASS_C); OrientDbWebSession.get().signOut(); } } private static class TestCallback implements CallbackHook.ICallback { @Override public boolean call(TYPE iType, ODocument doc) { assertEquals("testname", doc.field("name")); doc.field("callback"+iType, "executed", OType.STRING); return true; } }; @Test public void testCallbackHook() throws Exception { assertTrue(OrientDbWebSession.get().signIn("admin", "admin")); ODatabaseDocument db = OrientDbWebSession.get().getDatabase(); OSchema schema = db.getMetadata().getSchema(); OClass oClass = schema.createClass(TEST_CLASS_CALLBACK); oClass.createProperty("name", OType.STRING); try { ODocument doc = new ODocument(oClass); doc.field("name", "testname"); TestCallback callback = new TestCallback(); CallbackHook.registerCallback(doc, TYPE.AFTER_CREATE, callback); CallbackHook.registerCallback(doc, TYPE.BEFORE_CREATE, callback); doc.save(); assertEquals("executed", doc.field("callback"+TYPE.AFTER_CREATE)); assertEquals("executed", doc.field("callback"+TYPE.BEFORE_CREATE)); assertFalse(doc.containsField("__callbacks__")); doc.reload(); assertFalse(doc.containsField("__callbacks__")); assertFalse(doc.containsField("callback"+TYPE.AFTER_READ)); CallbackHook.registerCallback(doc, TYPE.AFTER_READ, callback); doc.reload(); assertEquals("executed", doc.field("callback"+TYPE.AFTER_READ)); } finally { schema.dropClass(TEST_CLASS_CALLBACK); OrientDbWebSession.get().signOut(); } } }