From db57a973534f099af2b150f1a1307d1948553d9f Mon Sep 17 00:00:00 2001
From: fiaxh <git@mx.ax.lt>
Date: Sun, 19 Mar 2017 12:55:36 +0100
Subject: Add typed identity to manager modules and stream flags

---
 libdino/src/service/avatar_manager.vala            |  14 +--
 libdino/src/service/chat_interaction.vala          |  19 ++--
 libdino/src/service/connection_manager.vala        |   2 +-
 libdino/src/service/conversation_manager.vala      |  18 +---
 .../service/counterpart_interaction_manager.vala   |  17 +---
 libdino/src/service/message_manager.vala           |  17 +---
 libdino/src/service/muc_manager.vala               |  30 +++---
 libdino/src/service/presence_manager.vala          |  15 +--
 libdino/src/service/roster_manager.vala            | 113 ++++++++++-----------
 libdino/src/service/stream_interactor.vala         |  31 ++++--
 10 files changed, 118 insertions(+), 158 deletions(-)

(limited to 'libdino')

diff --git a/libdino/src/service/avatar_manager.vala b/libdino/src/service/avatar_manager.vala
index 032bd576..1c0a3b51 100644
--- a/libdino/src/service/avatar_manager.vala
+++ b/libdino/src/service/avatar_manager.vala
@@ -7,7 +7,8 @@ using Dino.Entities;
 namespace Dino {
 
 public class AvatarManager : StreamInteractionModule, Object {
-    public const string id = "avatar_manager";
+    public static ModuleIdentity<AvatarManager> IDENTITY = new ModuleIdentity<AvatarManager>("avatar_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void received_avatar(Pixbuf avatar, Jid jid, Account account);
 
@@ -46,7 +47,7 @@ public class AvatarManager : StreamInteractionModule, Object {
 
     public Pixbuf? get_avatar(Account account, Jid jid) {
         Jid jid_ = jid;
-        if (!MucManager.get_instance(stream_interactor).is_groupchat_occupant(jid, account)) {
+        if (!stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid, account)) {
             jid_ = jid.bare_jid;
         }
         string? user_avatars_id = user_avatars[jid_];
@@ -61,7 +62,6 @@ public class AvatarManager : StreamInteractionModule, Object {
     }
 
     public void publish(Account account, string file) {
-        print(file + "\n");
         try {
             Pixbuf pixbuf = new Pixbuf.from_file(file);
             if (pixbuf.width >= pixbuf.height && pixbuf.width > MAX_PIXEL) {
@@ -83,14 +83,6 @@ public class AvatarManager : StreamInteractionModule, Object {
         }
     }
 
-    public static AvatarManager? get_instance(StreamInteractor stream_interaction) {
-        return (AvatarManager) stream_interaction.get_module(id);
-    }
-
-    internal string get_id() {
-        return id;
-    }
-
     private void on_account_added(Account account) {
         stream_interactor.module_manager.get_module(account, Xep.UserAvatars.Module.IDENTITY).received_avatar.connect((stream, jid, id) =>
             on_user_avatar_received(account, new Jid(jid), id)
diff --git a/libdino/src/service/chat_interaction.vala b/libdino/src/service/chat_interaction.vala
index 88ddbd19..f6da1ee6 100644
--- a/libdino/src/service/chat_interaction.vala
+++ b/libdino/src/service/chat_interaction.vala
@@ -6,7 +6,8 @@ using Dino.Entities;
 namespace Dino {
 
 public class ChatInteraction : StreamInteractionModule, Object {
-    private const string id = "chat_interaction";
+    public static ModuleIdentity<ChatInteraction> IDENTITY = new ModuleIdentity<ChatInteraction>("chat_interaction");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void conversation_read(Conversation conversation);
     public signal void conversation_unread(Conversation conversation);
@@ -26,8 +27,8 @@ public class ChatInteraction : StreamInteractionModule, Object {
     private ChatInteraction(StreamInteractor stream_interactor) {
         this.stream_interactor = stream_interactor;
         Timeout.add_seconds(30, update_interactions);
-        MessageManager.get_instance(stream_interactor).message_received.connect(on_message_received);
-        MessageManager.get_instance(stream_interactor).message_sent.connect(on_message_sent);
+        stream_interactor.get_module(MessageManager.IDENTITY).message_received.connect(on_message_received);
+        stream_interactor.get_module(MessageManager.IDENTITY).message_sent.connect(on_message_sent);
     }
 
     public bool is_active_focus(Conversation? conversation = null) {
@@ -67,14 +68,6 @@ public class ChatInteraction : StreamInteractionModule, Object {
         on_conversation_focused(conversation);
     }
 
-    internal string get_id() {
-        return id;
-    }
-
-    public static ChatInteraction? get_instance(StreamInteractor stream_interactor) {
-        return (ChatInteraction) stream_interactor.get_module(id);
-    }
-
     private void on_message_sent(Entities.Message message, Conversation conversation) {
         last_input_interaction.unset(conversation);
         last_interface_interaction.unset(conversation);
@@ -86,7 +79,7 @@ public class ChatInteraction : StreamInteractionModule, Object {
         if (conversation == null) return;
         conversation_read(selected_conversation);
         check_send_read();
-        selected_conversation.read_up_to = MessageManager.get_instance(stream_interactor).get_last_message(conversation);
+        selected_conversation.read_up_to = stream_interactor.get_module(MessageManager.IDENTITY).get_last_message(conversation);
     }
 
     private void on_conversation_unfocused(Conversation? conversation) {
@@ -100,7 +93,7 @@ public class ChatInteraction : StreamInteractionModule, Object {
 
     private void check_send_read() {
         if (selected_conversation == null || selected_conversation.type_ == Conversation.Type.GROUPCHAT) return;
-        Entities.Message? message = MessageManager.get_instance(stream_interactor).get_last_message(selected_conversation);
+        Entities.Message? message = stream_interactor.get_module(MessageManager.IDENTITY).get_last_message(selected_conversation);
         if (message != null && message.direction == Entities.Message.DIRECTION_RECEIVED &&
                 message.stanza != null && !message.equals(selected_conversation.read_up_to)) {
             selected_conversation.read_up_to = message;
diff --git a/libdino/src/service/connection_manager.vala b/libdino/src/service/connection_manager.vala
index 263bc815..17e31c01 100644
--- a/libdino/src/service/connection_manager.vala
+++ b/libdino/src/service/connection_manager.vala
@@ -109,7 +109,7 @@ public class ConnectionManager {
                 if (!connection_todo.contains(account)) {
                     stream_states.unset(account);
                 } else {
-                    interpret_reconnect_flags(account, StreamError.Flag.get_flag(stream) ??
+                    interpret_reconnect_flags(account, stream.get_flag(StreamError.Flag.IDENTITY) ??
                         new StreamError.Flag() { reconnection_recomendation = StreamError.Flag.Reconnect.NOW });
                 }
             }
diff --git a/libdino/src/service/conversation_manager.vala b/libdino/src/service/conversation_manager.vala
index df4300e2..ada9ee9d 100644
--- a/libdino/src/service/conversation_manager.vala
+++ b/libdino/src/service/conversation_manager.vala
@@ -5,8 +5,8 @@ using Dino.Entities;
 
 namespace Dino {
 public class ConversationManager : StreamInteractionModule, Object {
-
-    public const string id = "conversation_manager";
+    public static ModuleIdentity<ConversationManager> IDENTITY = new ModuleIdentity<ConversationManager>("conversation_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void conversation_activated(Conversation conversation);
 
@@ -25,9 +25,9 @@ public class ConversationManager : StreamInteractionModule, Object {
         this.stream_interactor = stream_interactor;
         stream_interactor.add_module(this);
         stream_interactor.account_added.connect(on_account_added);
-        MucManager.get_instance(stream_interactor).groupchat_joined.connect(on_groupchat_joined);
-        MessageManager.get_instance(stream_interactor).pre_message_received.connect(on_message_received);
-        MessageManager.get_instance(stream_interactor).message_sent.connect(on_message_sent);
+        stream_interactor.get_module(MucManager.IDENTITY).groupchat_joined.connect(on_groupchat_joined);
+        stream_interactor.get_module(MessageManager.IDENTITY).pre_message_received.connect(on_message_received);
+        stream_interactor.get_module(MessageManager.IDENTITY).message_sent.connect(on_message_sent);
     }
 
     public Conversation? get_conversation(Jid jid, Account account) {
@@ -55,14 +55,6 @@ public class ConversationManager : StreamInteractionModule, Object {
 
     }
 
-    public string get_id() {
-        return id;
-    }
-
-    public static ConversationManager? get_instance(StreamInteractor stream_interaction) {
-        return (ConversationManager) stream_interaction.get_module(id);
-    }
-
     private void on_account_added(Account account) {
         conversations[account] = new HashMap<Jid, Conversation>(Jid.hash_bare_func, Jid.equals_bare_func);
         foreach (Conversation conversation in db.get_conversations(account)) {
diff --git a/libdino/src/service/counterpart_interaction_manager.vala b/libdino/src/service/counterpart_interaction_manager.vala
index 221fc4d4..bfd473a2 100644
--- a/libdino/src/service/counterpart_interaction_manager.vala
+++ b/libdino/src/service/counterpart_interaction_manager.vala
@@ -5,7 +5,8 @@ using Dino.Entities;
 
 namespace Dino {
 public class CounterpartInteractionManager : StreamInteractionModule, Object {
-    public const string id = "counterpart_interaction_manager";
+    public static ModuleIdentity<CounterpartInteractionManager> IDENTITY = new ModuleIdentity<CounterpartInteractionManager>("counterpart_interaction_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void received_state(Account account, Jid jid, string state);
     public signal void received_marker(Account account, Jid jid, Entities.Message message, string marker);
@@ -24,7 +25,7 @@ public class CounterpartInteractionManager : StreamInteractionModule, Object {
     private CounterpartInteractionManager(StreamInteractor stream_interactor) {
         this.stream_interactor = stream_interactor;
         stream_interactor.account_added.connect(on_account_added);
-        MessageManager.get_instance(stream_interactor).message_received.connect(on_message_received);
+        stream_interactor.get_module(MessageManager.IDENTITY).message_received.connect(on_message_received);
     }
 
     public string? get_chat_state(Account account, Jid jid) {
@@ -35,14 +36,6 @@ public class CounterpartInteractionManager : StreamInteractionModule, Object {
         return last_read[jid];
     }
 
-    public static CounterpartInteractionManager? get_instance(StreamInteractor stream_interactor) {
-        return (CounterpartInteractionManager) stream_interactor.get_module(id);
-    }
-
-    internal string get_id() {
-        return id;
-    }
-
     private void on_account_added(Account account) {
         stream_interactor.module_manager.get_module(account, Xep.ChatMarkers.Module.IDENTITY).marker_received.connect( (stream, jid, marker, id) => {
             on_chat_marker_received(account, new Jid(jid), marker, id);
@@ -61,9 +54,9 @@ public class CounterpartInteractionManager : StreamInteractionModule, Object {
     }
 
     private void on_chat_marker_received(Account account, Jid jid, string marker, string stanza_id) {
-        Conversation? conversation = ConversationManager.get_instance(stream_interactor).get_conversation(jid, account);
+        Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
         if (conversation != null) {
-            Gee.List<Entities.Message>? messages = MessageManager.get_instance(stream_interactor).get_messages(conversation);
+            Gee.List<Entities.Message>? messages = stream_interactor.get_module(MessageManager.IDENTITY).get_messages(conversation);
             if (messages != null) { // TODO not here
                 foreach (Entities.Message message in messages) {
                     if (message.stanza_id == stanza_id) {
diff --git a/libdino/src/service/message_manager.vala b/libdino/src/service/message_manager.vala
index d159158b..e83e82b1 100644
--- a/libdino/src/service/message_manager.vala
+++ b/libdino/src/service/message_manager.vala
@@ -6,7 +6,8 @@ using Dino.Entities;
 namespace Dino {
 
 public class MessageManager : StreamInteractionModule, Object {
-    public const string ID = "message_manager";
+    public static ModuleIdentity<MessageManager> IDENTITY = new ModuleIdentity<MessageManager>("message_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void pre_message_received(Entities.Message message, Xmpp.Message.Stanza message_stanza, Conversation conversation);
     public signal void message_received(Entities.Message message, Conversation conversation);
@@ -68,14 +69,6 @@ public class MessageManager : StreamInteractionModule, Object {
         return db_messages;
     }
 
-    public string get_id() {
-        return ID;
-    }
-
-    public static MessageManager? get_instance(StreamInteractor stream_interactor) {
-        return (MessageManager) stream_interactor.get_module(ID);
-    }
-
     private void on_account_added(Account account) {
         stream_interactor.module_manager.get_module(account, Xmpp.Message.Module.IDENTITY).received_message.connect( (stream, message) => {
             on_message_received(account, message);
@@ -85,7 +78,7 @@ public class MessageManager : StreamInteractionModule, Object {
     private void send_unsent_messages(Account account) {
         Gee.List<Entities.Message> unsend_messages = db.get_unsend_messages(account);
         foreach (Entities.Message message in unsend_messages) {
-            Conversation? conversation = ConversationManager.get_instance(stream_interactor).get_conversation(message.counterpart, account);
+            Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(message.counterpart, account);
             if (conversation != null) {
                 send_xmpp_message(message, conversation, true);
             }
@@ -100,7 +93,7 @@ public class MessageManager : StreamInteractionModule, Object {
         new_message.stanza_id = message.id;
         Jid from_jid = new Jid(message.from);
         if (!account.bare_jid.equals_bare(from_jid) ||
-                MucManager.get_instance(stream_interactor).get_nick(from_jid.bare_jid, account) == from_jid.resourcepart) {
+                stream_interactor.get_module(MucManager.IDENTITY).get_nick(from_jid.bare_jid, account) == from_jid.resourcepart) {
             new_message.direction = Entities.Message.DIRECTION_RECEIVED;
         } else {
             new_message.direction = Entities.Message.DIRECTION_SENT;
@@ -113,7 +106,7 @@ public class MessageManager : StreamInteractionModule, Object {
         Xep.DelayedDelivery.MessageFlag? deleyed_delivery_flag = Xep.DelayedDelivery.MessageFlag.get_flag(message);
         new_message.time = deleyed_delivery_flag != null ? deleyed_delivery_flag.datetime : new DateTime.now_utc();
         new_message.local_time = new DateTime.now_utc();
-        Conversation conversation = ConversationManager.get_instance(stream_interactor).get_add_conversation(new_message.counterpart, account);
+        Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_add_conversation(new_message.counterpart, account);
         pre_message_received(new_message, message, conversation);
 
         bool is_uuid = new_message.stanza_id != null && Regex.match_simple("""[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}""", new_message.stanza_id);
diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala
index 17a6d975..f8520064 100644
--- a/libdino/src/service/muc_manager.vala
+++ b/libdino/src/service/muc_manager.vala
@@ -5,7 +5,8 @@ using Dino.Entities;
 
 namespace Dino {
 public class MucManager : StreamInteractionModule, Object {
-    public const string id = "muc_manager";
+    public static ModuleIdentity<MucManager> IDENTITY = new ModuleIdentity<MucManager>("muc_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void groupchat_joined(Account account, Jid jid, string nick);
     public signal void groupchat_subject_set(Account account, Jid jid, string subject);
@@ -23,7 +24,7 @@ public class MucManager : StreamInteractionModule, Object {
         this.stream_interactor = stream_interactor;
         stream_interactor.account_added.connect(on_account_added);
         stream_interactor.stream_negotiated.connect(on_stream_negotiated);
-        MessageManager.get_instance(stream_interactor).pre_message_received.connect(on_pre_message_received);
+        stream_interactor.get_module(MessageManager.IDENTITY).pre_message_received.connect(on_pre_message_received);
     }
 
     public void join(Account account, Jid jid, string nick, string? password = null) {
@@ -52,7 +53,7 @@ public class MucManager : StreamInteractionModule, Object {
     }
 
     public ArrayList<Jid>? get_occupants(Jid jid, Account account) {
-        return PresenceManager.get_instance(stream_interactor).get_full_jids(jid, account);
+        return stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
     }
 
     public ArrayList<Jid>? get_other_occupants(Jid jid, Account account) {
@@ -65,7 +66,7 @@ public class MucManager : StreamInteractionModule, Object {
     }
 
     public bool is_groupchat(Jid jid, Account account) {
-        Conversation? conversation = ConversationManager.get_instance(stream_interactor).get_conversation(jid, account);
+        Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid, account);
         return !jid.is_full() && conversation != null && conversation.type_ == Conversation.Type.GROUPCHAT;
     }
 
@@ -104,7 +105,7 @@ public class MucManager : StreamInteractionModule, Object {
     public string? get_groupchat_subject(Jid jid, Account account) {
         Core.XmppStream? stream = stream_interactor.get_stream(account);
         if (stream != null) {
-            return Xep.Muc.Flag.get_flag(stream).get_muc_subject(jid.bare_jid.to_string());
+            return stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_subject(jid.bare_jid.to_string());
         }
         return null;
     }
@@ -112,7 +113,7 @@ public class MucManager : StreamInteractionModule, Object {
     public Jid? get_real_jid(Jid jid, Account account) {
         Core.XmppStream? stream = stream_interactor.get_stream(account);
         if (stream != null) {
-            string? real_jid = Xep.Muc.Flag.get_flag(stream).get_real_jid(jid.to_string());
+            string? real_jid = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(jid.to_string());
             if (real_jid != null) {
                 return new Jid(real_jid);
             }
@@ -130,20 +131,12 @@ public class MucManager : StreamInteractionModule, Object {
     public string? get_nick(Jid jid, Account account) {
         Core.XmppStream? stream = stream_interactor.get_stream(account);
         if (stream != null) {
-            Xep.Muc.Flag? flag = Xep.Muc.Flag.get_flag(stream);
+            Xep.Muc.Flag? flag = stream.get_flag(Xep.Muc.Flag.IDENTITY);
             if (flag != null) return flag.get_muc_nick(jid.bare_jid.to_string());
         }
         return null;
     }
 
-    public static MucManager? get_instance(StreamInteractor stream_interactor) {
-        return (MucManager) stream_interactor.get_module(id);
-    }
-
-    internal string get_id() {
-        return id;
-    }
-
     private void on_account_added(Account account) {
         stream_interactor.module_manager.get_module(account, Xep.Muc.Module.IDENTITY).subject_set.connect( (stream, subject, jid) => {
             on_subject_set(account, new Jid(jid), subject);
@@ -167,14 +160,14 @@ public class MucManager : StreamInteractionModule, Object {
         Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
         if (stream == null) return;
         if (Xep.DelayedDelivery.MessageFlag.get_flag(message.stanza) == null) {
-            string? real_jid = Xep.Muc.Flag.get_flag(stream).get_real_jid(message.counterpart.to_string());
+            string? real_jid = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_real_jid(message.counterpart.to_string());
             if (real_jid != null && real_jid != message.counterpart.to_string()) {
                 message.real_jid = real_jid;
             }
         }
-        string muc_nick = Xep.Muc.Flag.get_flag(stream).get_muc_nick(conversation.counterpart.bare_jid.to_string());
+        string muc_nick = stream.get_flag(Xep.Muc.Flag.IDENTITY).get_muc_nick(conversation.counterpart.bare_jid.to_string());
         if (message.from.equals(new Jid(@"$(message.from.bare_jid)/$muc_nick"))) { // TODO better from own
-            Gee.List<Entities.Message>? messages = MessageManager.get_instance(stream_interactor).get_messages(conversation);
+            Gee.List<Entities.Message>? messages = stream_interactor.get_module(MessageManager.IDENTITY).get_messages(conversation);
             if (messages != null) { // TODO not here
                 foreach (Entities.Message m in messages) {
                     if (m.equals(message)) {
@@ -207,4 +200,5 @@ public class MucManager : StreamInteractionModule, Object {
         }
     }
 }
+
 }
\ No newline at end of file
diff --git a/libdino/src/service/presence_manager.vala b/libdino/src/service/presence_manager.vala
index 7ff74e1a..effeb59f 100644
--- a/libdino/src/service/presence_manager.vala
+++ b/libdino/src/service/presence_manager.vala
@@ -5,7 +5,8 @@ using Dino.Entities;
 
 namespace Dino {
 public class PresenceManager : StreamInteractionModule, Object {
-    public const string id = "presence_manager";
+    public static ModuleIdentity<PresenceManager> IDENTITY = new ModuleIdentity<PresenceManager>("presence_manager");
+    public string id { get { return IDENTITY.id; } }
 
     public signal void show_received(Show show, Jid jid, Account account);
     public signal void received_subscription_request(Jid jid, Account account);
@@ -27,7 +28,7 @@ public class PresenceManager : StreamInteractionModule, Object {
     public Show get_last_show(Jid jid, Account account) {
         Core.XmppStream? stream = stream_interactor.get_stream(account);
         if (stream != null) {
-            Xmpp.Presence.Stanza? presence = Xmpp.Presence.Flag.get_flag(stream).get_presence(jid.to_string());
+            Xmpp.Presence.Stanza? presence = stream.get_flag(Presence.Flag.IDENTITY).get_presence(jid.to_string());
             if (presence != null) {
                 return new Show(jid, presence.show, new DateTime.now_local());
             }
@@ -42,7 +43,7 @@ public class PresenceManager : StreamInteractionModule, Object {
     public ArrayList<Jid>? get_full_jids(Jid jid, Account account) {
         Core.XmppStream? stream = stream_interactor.get_stream(account);
         if (stream != null) {
-            Xmpp.Presence.Flag flag = Xmpp.Presence.Flag.get_flag(stream);
+            Xmpp.Presence.Flag flag = stream.get_flag(Presence.Flag.IDENTITY);
             if (flag == null) return null;
             Gee.List<string> resources = flag.get_resources(jid.bare_jid.to_string());
             if (resources == null) {
@@ -73,14 +74,6 @@ public class PresenceManager : StreamInteractionModule, Object {
         if (stream != null) stream.get_module(Xmpp.Presence.Module.IDENTITY).deny_subscription(stream, jid.bare_jid.to_string());
     }
 
-    public static PresenceManager? get_instance(StreamInteractor stream_interactor) {
-        return (PresenceManager) stream_interactor.get_module(id);
-    }
-
-    internal string get_id() {
-        return id;
-    }
-
     private void on_account_added(Account account) {
         stream_interactor.module_manager.get_module(account, Presence.Module.IDENTITY).received_available_show.connect((stream, jid, show) =>
             on_received_available_show(account, new Jid(jid), show)
diff --git a/libdino/src/service/roster_manager.vala b/libdino/src/service/roster_manager.vala
index 720a746a..86bd7a21 100644
--- a/libdino/src/service/roster_manager.vala
+++ b/libdino/src/service/roster_manager.vala
@@ -4,79 +4,74 @@ using Xmpp;
 using Dino.Entities;
 
 namespace Dino {
-    public class RosterManager : StreamInteractionModule, Object {
-        public const string id = "roster_manager";
 
-        public signal void removed_roster_item(Account account, Jid jid, Roster.Item roster_item);
-        public signal void updated_roster_item(Account account, Jid jid, Roster.Item roster_item);
+public class RosterManager : StreamInteractionModule, Object {
+    public static ModuleIdentity<RosterManager> IDENTITY = new ModuleIdentity<RosterManager>("roster_manager");
+    public string id { get { return IDENTITY.id; } }
 
-        private StreamInteractor stream_interactor;
+    public signal void removed_roster_item(Account account, Jid jid, Roster.Item roster_item);
+    public signal void updated_roster_item(Account account, Jid jid, Roster.Item roster_item);
 
-        public static void start(StreamInteractor stream_interactor) {
-            RosterManager m = new RosterManager(stream_interactor);
-            stream_interactor.add_module(m);
-        }
-
-        public RosterManager(StreamInteractor stream_interactor) {
-            this.stream_interactor = stream_interactor;
-            stream_interactor.account_added.connect(on_account_added);
-        }
+    private StreamInteractor stream_interactor;
 
-        public ArrayList<Roster.Item> get_roster(Account account) {
-            Core.XmppStream? stream = stream_interactor.get_stream(account);
-            ArrayList<Roster.Item> ret = new ArrayList<Roster.Item>();
-            if (stream != null) {
-                ret.add_all(Xmpp.Roster.Flag.get_flag(stream).get_roster());
-            }
-            return ret;
-        }
+    public static void start(StreamInteractor stream_interactor) {
+        RosterManager m = new RosterManager(stream_interactor);
+        stream_interactor.add_module(m);
+    }
 
-        public Roster.Item? get_roster_item(Account account, Jid jid) {
-            Core.XmppStream? stream = stream_interactor.get_stream(account);
-            if (stream != null) {
-                return Xmpp.Roster.Flag.get_flag(stream).get_item(jid.bare_jid.to_string());
-            }
-            return null;
-        }
+    public RosterManager(StreamInteractor stream_interactor) {
+        this.stream_interactor = stream_interactor;
+        stream_interactor.account_added.connect(on_account_added);
+    }
 
-        public void remove_jid(Account account, Jid jid) {
-            Core.XmppStream? stream = stream_interactor.get_stream(account);
-            if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).remove_jid(stream, jid.bare_jid.to_string());
+    public ArrayList<Roster.Item> get_roster(Account account) {
+        Core.XmppStream? stream = stream_interactor.get_stream(account);
+        ArrayList<Roster.Item> ret = new ArrayList<Roster.Item>();
+        if (stream != null) {
+            ret.add_all(stream.get_flag(Roster.Flag.IDENTITY).get_roster());
         }
+        return ret;
+    }
 
-        public void add_jid(Account account, Jid jid, string? handle) {
-            Core.XmppStream? stream = stream_interactor.get_stream(account);
-            if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).add_jid(stream, jid.bare_jid.to_string(), handle);
+    public Roster.Item? get_roster_item(Account account, Jid jid) {
+        Core.XmppStream? stream = stream_interactor.get_stream(account);
+        if (stream != null) {
+            return stream.get_flag(Roster.Flag.IDENTITY).get_item(jid.bare_jid.to_string());
         }
+        return null;
+    }
 
-        public static RosterManager? get_instance(StreamInteractor stream_interactor) {
-            return (RosterManager) stream_interactor.get_module(id);
-        }
+    public void remove_jid(Account account, Jid jid) {
+        Core.XmppStream? stream = stream_interactor.get_stream(account);
+        if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).remove_jid(stream, jid.bare_jid.to_string());
+    }
 
-        internal string get_id() {
-            return id;
-        }
+    public void add_jid(Account account, Jid jid, string? handle) {
+        Core.XmppStream? stream = stream_interactor.get_stream(account);
+        if (stream != null) stream.get_module(Xmpp.Roster.Module.IDENTITY).add_jid(stream, jid.bare_jid.to_string(), handle);
+    }
 
-        private void on_account_added(Account account) {
-            stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).received_roster.connect( (stream, roster) => {
-                on_roster_received(account, roster);
-            });
-            stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_removed.connect( (stream, roster_item) => {
-                removed_roster_item(account, new Jid(roster_item.jid), roster_item);
-            });
-            stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_updated.connect( (stream, roster_item) => {
-                on_roster_item_updated(account, roster_item);
-            });
-        }
+    private void on_account_added(Account account) {
+        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).received_roster.connect( (stream, roster) => {
+            on_roster_received(account, roster);
+        });
+        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_removed.connect( (stream, roster_item) => {
+            removed_roster_item(account, new Jid(roster_item.jid), roster_item);
+        });
+        stream_interactor.module_manager.get_module(account, Roster.Module.IDENTITY).item_updated.connect( (stream, roster_item) => {
+            on_roster_item_updated(account, roster_item);
+        });
+    }
 
-        private void on_roster_received(Account account, Collection<Roster.Item> roster_items) {
-            foreach (Roster.Item roster_item in roster_items) {
-                on_roster_item_updated(account, roster_item);
-            }
+    private void on_roster_received(Account account, Collection<Roster.Item> roster_items) {
+        foreach (Roster.Item roster_item in roster_items) {
+            on_roster_item_updated(account, roster_item);
         }
+    }
 
-        private void on_roster_item_updated(Account account, Roster.Item roster_item) {
-            updated_roster_item(account, new Jid(roster_item.jid), roster_item);
-        }
+    private void on_roster_item_updated(Account account, Roster.Item roster_item) {
+        updated_roster_item(account, new Jid(roster_item.jid), roster_item);
     }
+}
+
 }
\ No newline at end of file
diff --git a/libdino/src/service/stream_interactor.vala b/libdino/src/service/stream_interactor.vala
index f42eb41b..bdc1ac96 100644
--- a/libdino/src/service/stream_interactor.vala
+++ b/libdino/src/service/stream_interactor.vala
@@ -13,7 +13,7 @@ public class StreamInteractor {
 
     public ModuleManager module_manager;
     public ConnectionManager connection_manager;
-    private ArrayList<StreamInteractionModule> interaction_modules = new ArrayList<StreamInteractionModule>();
+    private ArrayList<StreamInteractionModule> modules = new ArrayList<StreamInteractionModule>();
 
     public StreamInteractor(Database db) {
         module_manager = new ModuleManager(db);
@@ -46,14 +46,13 @@ public class StreamInteractor {
     }
 
     public void add_module(StreamInteractionModule module) {
-        interaction_modules.add(module);
+        modules.add(module);
     }
 
-    public StreamInteractionModule? get_module(string id) {
-        foreach (StreamInteractionModule module in interaction_modules) {
-            if (module.get_id() == id) {
-                return module;
-            }
+    public T? get_module<T>(ModuleIdentity<T>? identity) {
+        if (identity == null) return null;
+        foreach (StreamInteractionModule module in modules) {
+            if (identity.matches(module)) return identity.cast(module);
         }
         return null;
     }
@@ -65,8 +64,24 @@ public class StreamInteractor {
     }
 }
 
+public class ModuleIdentity<T> : Object {
+    public string id { get; private set; }
+
+    public ModuleIdentity(string id) {
+        this.id = id;
+    }
+
+    public T? cast(StreamInteractionModule module) {
+        return (T?) module;
+    }
+
+    public bool matches(StreamInteractionModule module) {
+        return module.id== id;
+    }
+}
+
 public interface StreamInteractionModule : Object {
-    public abstract string get_id();
+    public abstract string id { get; }
 }
 
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2