--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.tests.api.request.listening;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.procedure.adapter.AsyncListenerAdapter;
+import org.simantics.db.common.request.ResourceAsyncRead;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.procedure.AsyncProcedure;
+import org.simantics.db.testing.base.ExistingDatabaseTest;
+import org.simantics.layer0.Layer0;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class EqualListenerDisposeTest extends ExistingDatabaseTest {
+
+ static class TestRequest extends ResourceAsyncRead<String> {
+ public TestRequest(Resource resource) {
+ super(resource);
+ }
+ @Override
+ public void perform(AsyncReadGraph graph, AsyncProcedure<String> procedure) {
+ Layer0 b;
+ try {
+ b = Layer0.getInstance(graph.getSession());
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ throw new RuntimeDatabaseException(e);
+ }
+ graph.forRelatedValue(resource, b.HasName, procedure);
+ }
+ }
+
+ static class TestListener extends AsyncListenerAdapter<String> {
+ String id;
+ AtomicInteger execs = new AtomicInteger();
+ AtomicBoolean disposed = new AtomicBoolean(false);
+ public TestListener(String id) {
+ this.id = id;
+ }
+ public int getExecs() {
+ return execs.get();
+ }
+ public void dispose() {
+ disposed.set(true);
+ }
+ @Override
+ public boolean isDisposed() {
+ return disposed.get();
+ }
+ @Override
+ public void execute(AsyncReadGraph graph, String result) {
+ int c = execs.incrementAndGet();
+ if (DEBUG)
+ System.out.println("Listener(" + id + ").execute(" + result + "), execution #" + c);
+ }
+ @Override
+ public int hashCode() {
+ return TestListener.class.hashCode();
+ }
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof TestListener;
+ }
+ }
+
+ Resource testResource;
+
+ @Test
+ public void testMultipleListeners() throws Exception {
+ final Session session = getSession();
+
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(graph);
+ testResource = graph.newResource();
+ graph.claim(testResource, b.InstanceOf, null, b.Entity);
+ graph.claimLiteral(testResource, b.HasName, "Test Entity", Bindings.STRING);
+ }
+ });
+
+ TestListener l1 = new TestListener("L1");
+ TestListener l2 = new TestListener("L2");
+ session.syncRequest(new TestRequest(testResource), l1);
+
+ assertEquals(l1.getExecs(), 1);
+
+ // Make a modification that should be notified for
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(graph);
+ graph.claimLiteral(testResource, b.HasName, "Test Entity (modified name)", Bindings.STRING);
+ }
+ });
+
+ assertEquals(l1.getExecs(), 2);
+
+ // The listener should be fired but not listened to (there is already an equal listener)
+ session.syncRequest(new TestRequest(testResource), l2);
+
+ assertEquals(l1.getExecs(), 2);
+ assertEquals(l2.getExecs(), 1);
+
+ if (DEBUG)
+ System.out.println("Dispose listener L1");
+ l1.dispose();
+
+ // The listener should be fired and listened to (previous equal listener is disposed)
+ session.syncRequest(new TestRequest(testResource), l2);
+
+ assertEquals(l1.getExecs(), 2);
+ assertEquals(l2.getExecs(), 2);
+
+ if (DEBUG)
+ System.out.println("Make modification, should fire l2");
+ // Make a modification that should be notified for
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(graph);
+ graph.claimLiteral(testResource, b.HasName, "Test Entity (modified name 2)", Bindings.STRING);
+ }
+ });
+
+ assertEquals(l1.getExecs(), 2);
+ assertEquals(l2.getExecs(), 3);
+
+ if (DEBUG)
+ System.out.println("Dispose listener L2");
+ l2.dispose();
+
+ if (DEBUG)
+ System.out.println("Make another modification, should not fire");
+ // Make a modification that should be notified for
+ session.syncRequest(new WriteRequest() {
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ Layer0 b = Layer0.getInstance(graph);
+ graph.claimLiteral(testResource, b.HasName, "Test Entity (even more modified name)", Bindings.STRING);
+ }
+ });
+
+ assertEquals(l1.getExecs(), 2);
+ assertEquals(l2.getExecs(), 3);
+
+ }
+}