package org.exist.fluent;
import static org.junit.Assert.*;
import org.hamcrest.*;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Action;
import org.jmock.api.Invocation;
import org.jmock.integration.junit4.*;
import org.junit.*;
import org.junit.runner.RunWith;
@RunWith(JMock.class)
public class ListenerManagerTest extends DatabaseTestCase {
private Mockery context = new JUnit4Mockery();
private Document.Listener documentListener;
private Folder.Listener folderListener;
@Before public void prepareMocks() {
documentListener = context.mock(Document.Listener.class, "documentListener");
folderListener = context.mock(Folder.Listener.class, "folderListener");
}
@After public void unregisterMocks() throws Exception {
if (documentListener != null) ListenerManager.INSTANCE.remove(documentListener);
if (folderListener != null) ListenerManager.INSTANCE.remove(folderListener);
documentListener = null;
folderListener = null;
}
private Matcher<Document.Event> eqDelayedDoc(final Document.Event ev) {
return new BaseMatcher<Document.Event>() {
public void describeTo(Description desc) {
desc.appendText("eqDelayedDoc(").appendValue(ev).appendText(")");
}
public boolean matches(Object o) {
return new Document.Event(ev.trigger, ev.path, db.getDocument(ev.path)).equals(o);
}
};
}
private Action checkDocumentExists(final String path, final boolean shouldExist) {
return new Action() {
public void describeTo(Description desc) {
desc.appendText("check that document '" + path + "' " + (shouldExist ? "exists" : "does not exist"));
}
public Object invoke(Invocation inv) throws Throwable {
try {
db.getDocument(path);
if (!shouldExist) fail("document '" + path + "' exists but shouldn't");
} catch (DatabaseException e) {
if (shouldExist) fail("document '" + path + "' doesn't exist but should");
}
return null;
}
};
}
private Action checkFolderExists(final String path, final boolean shouldExist) {
return new Action() {
public void describeTo(Description desc) {
desc.appendText("check that folder '" + path + "' " + (shouldExist ? "exists" : "does not exist"));
}
public Object invoke(Invocation inv) throws Throwable {
try {
db.getFolder(path);
if (!shouldExist) fail("folder '" + path + "' exists but shouldn't");
} catch (DatabaseException e) {
if (shouldExist) fail("folder '" + path + "' doesn't exist but should");
}
return null;
}
};
}
private Action checkDocumentStamp(final String expectedStamp) {
return new Action() {
public void describeTo(Description desc) {
desc.appendText("check that event document is stamped with '" + expectedStamp + "'");
}
public Object invoke(Invocation inv) throws Throwable {
XMLDocument doc = ((Document.Event) inv.getParameter(0)).document.xml();
assertNotNull("event document is null", doc);
assertEquals(expectedStamp, doc.query().single("/test/@stamp").value());
return null;
}
};
}
private XMLDocument createDocument(String path) {
return createDocument(path, null);
}
private XMLDocument createDocument(String path, String stamp) {
int k = path.lastIndexOf('/');
assert k > 0;
Folder folder = db.createFolder(path.substring(0, k));
return folder.documents().build(Name.overwrite(path.substring(k + 1)))
.elem("test").attrIf(stamp != null, "stamp", stamp).end("test")
.commit();
}
@Test public void listenDocumentsBeforeCreateDocument1() {
final String docPath = "/top/test.xml";
final Document.Event ev = new Document.Event(Trigger.BEFORE_CREATE, docPath, null);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
top.documents().listeners().add(Trigger.BEFORE_CREATE, documentListener);
createDocument(docPath);
createDocument("/elsewhere/test.xml");
createDocument("/top/deeper/test.xml");
}
@Test public void listenDocumentsBeforeCreateDocument2() {
final String docPath = "/top/test.xml";
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
never(documentListener).handle(with(any(Document.Event.class)));
}});
top.documents().listeners().add(Trigger.BEFORE_CREATE, documentListener);
top.documents().listeners().remove(documentListener);
createDocument(docPath);
}
@Test public void listenDocumentsAfterCreateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.AFTER_CREATE, docPath, doc);
doc.delete();
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(with(eqDelayedDoc(ev))); will(checkDocumentExists(docPath, true));
}});
top.documents().listeners().add(Trigger.AFTER_CREATE, documentListener);
createDocument(docPath);
createDocument("/elsewhere/test.xml");
createDocument("/top/deeper/test.xml");
}
@Test public void listenDocumentsAfterCreateDocument2() {
final String docPath = "/top/test.xml";
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
never(documentListener).handle(with(any(Document.Event.class)));
}});
top.documents().listeners().add(Trigger.AFTER_CREATE, documentListener);
top.documents().listeners().remove(documentListener);
createDocument(docPath);
}
@Test public void listenFolderBeforeCreateDocument1() {
final String docPath = "/top/test2.xml";
final Document.Event ev = new Document.Event(Trigger.BEFORE_CREATE, docPath, null);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
top.listeners().add(Trigger.BEFORE_CREATE, documentListener);
createDocument(docPath);
createDocument("/elsewhere/test.xml");
}
@Test public void listenFolderBeforeCreateDocument2() {
final String docPath = "/top/test2.xml";
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
never(documentListener).handle(with(any(Document.Event.class)));
}});
top.listeners().add(Trigger.BEFORE_CREATE, documentListener);
top.listeners().remove(documentListener);
createDocument(docPath);
}
@Test public void listenFolderAfterCreateDocument1() {
final String docPath = "/top/test2.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.AFTER_CREATE, docPath, doc);
doc.delete();
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(with(eqDelayedDoc(ev))); will(checkDocumentExists(docPath, true));
}});
top.listeners().add(Trigger.AFTER_CREATE, documentListener);
createDocument(docPath);
createDocument("/elsewhere/test.xml");
}
@Test public void listenFolderAfterCreateDocument2() {
final String docPath = "/top/test2.xml";
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
never(documentListener).handle(with(any(Document.Event.class)));
}});
top.listeners().add(Trigger.AFTER_CREATE, documentListener);
top.listeners().remove(documentListener);
createDocument(docPath);
}
@Test public void listenDocumentsBeforeUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.BEFORE_UPDATE, docPath, doc);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("before"));
}});
top.documents().listeners().add(Trigger.BEFORE_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
createDocument("/top/deeper/test.xml");
}
@Test public void listenDocumentsAfterUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.AFTER_UPDATE, docPath, doc);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("after"));
}});
top.documents().listeners().add(Trigger.AFTER_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
createDocument("/top/deeper/test.xml");
}
@Test public void listenFolderBeforeUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.BEFORE_UPDATE, docPath, doc);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("before"));
}});
top.listeners().add(Trigger.BEFORE_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
}
@Test public void listenFolderAfterUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.AFTER_UPDATE, docPath, doc);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("after"));
}});
top.listeners().add(Trigger.AFTER_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
}
@Test public void listenFolderDeepBeforeCreateDocument1() {
final String docPath = "/top/middle/test2.xml";
final Document.Event ev = new Document.Event(Trigger.BEFORE_CREATE, docPath, null);
Folder top = db.createFolder("/top");
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
top.listeners().add(Trigger.BEFORE_CREATE, documentListener);
createDocument(docPath);
createDocument("/elsewhere/test.xml");
}
@Test public void listenDocumentBeforeUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.BEFORE_UPDATE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("before"));
}});
doc.listeners().add(Trigger.BEFORE_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
createDocument("/top/test2.xml");
}
@Test public void listenDocumentAfterUpdateDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
final Document.Event ev = new Document.Event(Trigger.AFTER_UPDATE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentStamp("after"));
}});
doc.listeners().add(Trigger.AFTER_UPDATE, documentListener);
createDocument(docPath, "after");
createDocument("/elsewhere/test.xml");
createDocument("/top/test2.xml");
}
@Test public void listenDocumentsBeforeDeleteDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.BEFORE_DELETE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, true));
}});
Folder top = db.createFolder("/top");
top.documents().listeners().add(Trigger.BEFORE_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
createDocument("/top/deeper/test.xml").delete();
}
@Test public void listenDocumentsBeforeDeleteDocument2() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath, "before");
doc.delete();
final Document.Event ev = new Document.Event(Trigger.BEFORE_DELETE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(with(eqDelayedDoc(ev))); will(checkDocumentExists(docPath, true));
}});
Folder top = db.createFolder("/top");
top.documents().listeners().add(Trigger.BEFORE_DELETE, documentListener);
createDocument(docPath).delete();
createDocument("/elsewhere/test.xml").delete();
createDocument("/top/deeper/test.xml").delete();
}
@Test public void listenDocumentsAfterDeleteDocument1() {
final String docPath = "/top/test.xml";
final Document.Event ev = new Document.Event(Trigger.AFTER_DELETE, docPath, null);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
Folder top = db.createFolder("/top");
top.documents().listeners().add(Trigger.AFTER_DELETE, documentListener);
createDocument(docPath).delete();
createDocument("/elsewhere/test.xml").delete();
createDocument("/top/deeper/test.xml").delete();
}
@Test public void listenFolderBeforeDeleteDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.BEFORE_DELETE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, true));
}});
Folder top = db.createFolder("/top");
top.listeners().add(Trigger.BEFORE_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
}
@Test public void listenFolderBeforeDeleteDocument2() {
final String docPath = "/top/deeper/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.BEFORE_DELETE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, true));
}});
Folder top = db.createFolder("/top");
top.listeners().add(Trigger.BEFORE_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
}
@Test public void listenFolderAfterDeleteDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.AFTER_DELETE, docPath, null);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
Folder top = db.createFolder("/top");
top.listeners().add(Trigger.AFTER_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
}
@Test public void listenFolderAfterDeleteDocument2() {
final String docPath = "/top/deeper/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.AFTER_DELETE, docPath, null);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
Folder top = db.createFolder("/top");
top.listeners().add(Trigger.AFTER_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
}
@Test public void listenDocumentBeforeDeleteDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.BEFORE_DELETE, docPath, doc);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, true));
}});
doc.listeners().add(Trigger.BEFORE_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
createDocument("/top/deeper/test.xml").delete();
createDocument("/top/test2.xml").delete();
}
@Test public void listenDocumentAfterDeleteDocument1() {
final String docPath = "/top/test.xml";
XMLDocument doc = createDocument(docPath);
final Document.Event ev = new Document.Event(Trigger.AFTER_DELETE, docPath, null);
context.checking(new Expectations() {{
one(documentListener).handle(ev); will(checkDocumentExists(docPath, false));
}});
doc.listeners().add(Trigger.AFTER_DELETE, documentListener);
doc.delete();
createDocument("/elsewhere/test.xml").delete();
createDocument("/top/deeper/test.xml").delete();
createDocument("/top/test2.xml").delete();
}
@Test @Ignore("not yet implemented") public void listenBeforeCreateFolder1() {
final String folderPath = "/top/child";
final Folder.Event ev = new Folder.Event(Trigger.BEFORE_CREATE, folderPath, null);
context.checking(new Expectations() {{
one(folderListener).handle(ev); will(checkFolderExists(folderPath, false));
}});
Folder top = db.createFolder("/top");
top.listeners().add(Trigger.BEFORE_CREATE, folderListener);
top.children().create("child");
}
@Test @Ignore("not yet implemented") public void listenBeforeCreateFolder2() {
final String folderPath = "/top/middle/child";
final Folder.Event ev = new Folder.Event(Trigger.BEFORE_CREATE, folderPath, null);
context.checking(new Expectations() {{
one(folderListener).handle(ev); will(checkFolderExists(folderPath, false));
}});
Folder top = db.createFolder("/top");
Folder middle = db.createFolder("/top/middle");
top.listeners().add(Trigger.BEFORE_CREATE, folderListener);
middle.children().create("child");
}
}