From cdb5a12156e4b69d5b48d4d540f3fde08ade37e1 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Fri, 3 Oct 2014 10:04:02 +0100
Subject: [PATCH] Use the event bus to observe contacts connecting and
 disconnecting.

---
 .../android/contact/ContactListActivity.java  | 19 +++++--------
 .../api/event/ContactConnectedEvent.java      | 20 ++++++++++++++
 .../api/event/ContactDisconnectedEvent.java   | 20 ++++++++++++++
 .../api/transport/ConnectionListener.java     | 13 ---------
 .../api/transport/ConnectionRegistry.java     |  4 ---
 .../transport/ConnectionRegistryImpl.java     | 26 ++++++++----------
 .../transport/TransportModule.java            |  7 ++---
 .../transport/ConnectionRegistryImplTest.java | 27 ++++++++++++++++---
 8 files changed, 85 insertions(+), 51 deletions(-)
 create mode 100644 briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
 create mode 100644 briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
 delete mode 100644 briar-api/src/org/briarproject/api/transport/ConnectionListener.java

diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
index b72a0276b3..9e46afac57 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
@@ -31,6 +31,8 @@ import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.MessageHeader;
 import org.briarproject.api.db.NoSuchContactException;
 import org.briarproject.api.event.ContactAddedEvent;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
 import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
@@ -38,7 +40,6 @@ import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.MessageExpiredEvent;
 import org.briarproject.api.messaging.GroupId;
-import org.briarproject.api.transport.ConnectionListener;
 import org.briarproject.api.transport.ConnectionRegistry;
 
 import android.content.Intent;
@@ -61,7 +62,7 @@ import android.widget.Toast;
 
 public class ContactListActivity extends BriarActivity
 implements OnClickListener, OnItemClickListener, OnCreateContextMenuListener,
-EventListener, ConnectionListener {
+EventListener {
 
 	private static final int MENU_ITEM_DELETE = 1;
 	private static final Logger LOG =
@@ -128,7 +129,6 @@ EventListener, ConnectionListener {
 	public void onResume() {
 		super.onResume();
 		eventBus.addListener(this);
-		connectionRegistry.addListener(this);
 		loadContacts();
 	}
 
@@ -213,7 +213,6 @@ EventListener, ConnectionListener {
 	public void onPause() {
 		super.onPause();
 		eventBus.removeListener(this);
-		connectionRegistry.removeListener(this);
 	}
 
 	public void onClick(View view) {
@@ -271,6 +270,10 @@ EventListener, ConnectionListener {
 	public void eventOccurred(Event e) {
 		if(e instanceof ContactAddedEvent) {
 			loadContacts();
+		} else if(e instanceof ContactConnectedEvent) {
+			setConnected(((ContactConnectedEvent) e).getContactId(), true);
+		} else if(e instanceof ContactDisconnectedEvent) {
+			setConnected(((ContactDisconnectedEvent) e).getContactId(), false);
 		} else if(e instanceof ContactRemovedEvent) {
 			LOG.info("Contact removed");
 			removeItem(((ContactRemovedEvent) e).getContactId());
@@ -335,14 +338,6 @@ EventListener, ConnectionListener {
 		});
 	}
 
-	public void contactConnected(ContactId c) {
-		setConnected(c, true);
-	}
-
-	public void contactDisconnected(ContactId c) {
-		setConnected(c, false);
-	}
-
 	private void setConnected(final ContactId c, final boolean connected) {
 		runOnUiThread(new Runnable() {
 			public void run() {
diff --git a/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java b/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
new file mode 100644
index 0000000000..42c8bf7b82
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
@@ -0,0 +1,20 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.ContactId;
+
+/**
+ * An event that is broadcast when a contact connects that was not previously
+ * connected via any transport.
+ */
+public class ContactConnectedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactConnectedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java b/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
new file mode 100644
index 0000000000..a0f858dfd1
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
@@ -0,0 +1,20 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.ContactId;
+
+/**
+ * An event that is broadcast when a contact disconnects and is no longer
+ * connected via any transport.
+ */
+public class ContactDisconnectedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactDisconnectedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/transport/ConnectionListener.java b/briar-api/src/org/briarproject/api/transport/ConnectionListener.java
deleted file mode 100644
index 33052565bc..0000000000
--- a/briar-api/src/org/briarproject/api/transport/ConnectionListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.transport;
-
-import org.briarproject.api.ContactId;
-
-/** An interface for listening for connection and disconnection events. */
-public interface ConnectionListener {
-
-	/** Called when a contact connects and has no existing connections. */
-	void contactConnected(ContactId c);
-
-	/** Called when a contact disconnects and has no remaining connections. */
-	void contactDisconnected(ContactId c);
-}
diff --git a/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java b/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
index 270ea4b640..91a5a3da45 100644
--- a/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
+++ b/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
@@ -10,10 +10,6 @@ import org.briarproject.api.TransportId;
  */
 public interface ConnectionRegistry {
 
-	void addListener(ConnectionListener c);
-
-	void removeListener(ConnectionListener c);
-
 	void registerConnection(ContactId c, TransportId t);
 
 	void unregisterConnection(ContactId c, TransportId t);
diff --git a/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java b/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
index 94a2b93ea4..2e7485faa5 100644
--- a/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
+++ b/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
@@ -8,37 +8,33 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.logging.Logger;
 
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
-import org.briarproject.api.transport.ConnectionListener;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.transport.ConnectionRegistry;
 
+import com.google.inject.Inject;
+
 class ConnectionRegistryImpl implements ConnectionRegistry {
 
 	private static final Logger LOG =
 			Logger.getLogger(ConnectionRegistryImpl.class.getName());
 
+	private final EventBus eventBus;
 	// Locking: this
 	private final Map<TransportId, Map<ContactId, Integer>> connections;
 	// Locking: this
 	private final Map<ContactId, Integer> contactCounts;
-	private final List<ConnectionListener> listeners;
 
-	ConnectionRegistryImpl() {
+	@Inject
+	ConnectionRegistryImpl(EventBus eventBus) {
+		this.eventBus = eventBus;
 		connections = new HashMap<TransportId, Map<ContactId, Integer>>();
 		contactCounts = new HashMap<ContactId, Integer>();
-		listeners = new CopyOnWriteArrayList<ConnectionListener>();
-	}
-
-	public void addListener(ConnectionListener c) {
-		listeners.add(c);
-	}
-
-	public void removeListener(ConnectionListener c) {
-		listeners.remove(c);
 	}
 
 	public void registerConnection(ContactId c, TransportId t) {
@@ -63,7 +59,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
 		}
 		if(firstConnection) {
 			LOG.info("Contact connected");
-			for(ConnectionListener l : listeners) l.contactConnected(c);
+			eventBus.broadcast(new ContactConnectedEvent(c));
 		}
 	}
 
@@ -91,7 +87,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
 		}
 		if(lastConnection) {
 			LOG.info("Contact disconnected");
-			for(ConnectionListener l : listeners) l.contactDisconnected(c);
+			eventBus.broadcast(new ContactDisconnectedEvent(c));
 		}
 	}
 
diff --git a/briar-core/src/org/briarproject/transport/TransportModule.java b/briar-core/src/org/briarproject/transport/TransportModule.java
index 3fec3a8068..6ac7a15c93 100644
--- a/briar-core/src/org/briarproject/transport/TransportModule.java
+++ b/briar-core/src/org/briarproject/transport/TransportModule.java
@@ -22,9 +22,10 @@ public class TransportModule extends AbstractModule {
 				ConnectionReaderFactoryImpl.class);
 		bind(ConnectionRecogniser.class).to(
 				ConnectionRecogniserImpl.class).in(Singleton.class);
-		bind(ConnectionRegistry.class).toInstance(new ConnectionRegistryImpl());
-		bind(ConnectionWriterFactory.class).to(
-				ConnectionWriterFactoryImpl.class);
+		bind(ConnectionRegistry.class).to(
+				ConnectionRegistryImpl.class).in(Singleton.class);;
+				bind(ConnectionWriterFactory.class).to(
+						ConnectionWriterFactoryImpl.class);
 	}
 
 	@Provides @Singleton
diff --git a/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java b/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
index a6786db678..58a12f437f 100644
--- a/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
+++ b/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
@@ -7,7 +7,12 @@ import java.util.Collections;
 import org.briarproject.BriarTestCase;
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.transport.ConnectionRegistry;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
 import org.junit.Test;
 
 public class ConnectionRegistryImplTest extends BriarTestCase {
@@ -24,13 +29,24 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 
 	@Test
 	public void testRegisterAndUnregister() {
-		ConnectionRegistry c = new ConnectionRegistryImpl();
+		Mockery context = new Mockery();
+		final EventBus eventBus = context.mock(EventBus.class);
+		context.checking(new Expectations() {{
+			exactly(3).of(eventBus).broadcast(with(any(
+					ContactConnectedEvent.class)));
+			oneOf(eventBus).broadcast(with(any(
+					ContactDisconnectedEvent.class)));
+		}});
+
+		ConnectionRegistry c = new ConnectionRegistryImpl(eventBus);
+
 		// The registry should be empty
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId));
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId1));
-		// Check that a registered connection shows up
+		// Check that a registered connection shows up - this should
+		// broadcast a ContactConnectedEvent
 		c.registerConnection(contactId, transportId);
 		assertEquals(Arrays.asList(contactId),
 				c.getConnectedContacts(transportId));
@@ -48,7 +64,8 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 				c.getConnectedContacts(transportId));
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId1));
-		// Unregister the other connection - lookup should be affected
+		// Unregister the other connection - lookup should be affected -
+		// this should broadcast a ContactDisconnectedEvent
 		c.unregisterConnection(contactId, transportId);
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId));
@@ -59,7 +76,8 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 			c.unregisterConnection(contactId, transportId);
 			fail();
 		} catch(IllegalArgumentException expected) {}
-		// Register both contacts with one transport, one contact with both
+		// Register both contacts with one transport, one contact with both -
+		// this should broadcast two ContactConnectedEvents
 		c.registerConnection(contactId, transportId);
 		c.registerConnection(contactId1, transportId);
 		c.registerConnection(contactId1, transportId1);
@@ -69,5 +87,6 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 		assertTrue(connected.contains(contactId1));
 		assertEquals(Arrays.asList(contactId1),
 				c.getConnectedContacts(transportId1));
+		context.assertIsSatisfied();
 	}
 }
-- 
GitLab