using Gee; using Qlite; using Dino.Entities; namespace Dino { public class MessageStorage : StreamInteractionModule, Object { public static ModuleIdentity IDENTITY = new ModuleIdentity("message_cache"); public string id { get { return IDENTITY.id; } } private StreamInteractor stream_interactor; private Database db; private HashMap> messages = new HashMap>(Conversation.hash_func, Conversation.equals_func); public static void start(StreamInteractor stream_interactor, Database db) { MessageStorage m = new MessageStorage(stream_interactor, db); stream_interactor.add_module(m); } private MessageStorage(StreamInteractor stream_interactor, Database db) { this.stream_interactor = stream_interactor; this.db = db; } public void add_message(Message message, Conversation conversation) { message.persist(db); init_conversation(conversation); messages[conversation].add(message); } public Gee.List get_messages(Conversation conversation, int count = 50) { init_conversation(conversation); Gee.List ret = new ArrayList(Message.equals_func); BidirIterator iter = messages[conversation].bidir_iterator(); iter.last(); if (messages[conversation].size > 0) { do { ret.insert(0, iter.get()); iter.previous(); } while (iter.has_previous() && ret.size < count); } return ret; } public Message? get_last_message(Conversation conversation) { init_conversation(conversation); if (messages[conversation].size > 0) { return messages[conversation].last(); } return null; } public Gee.List get_messages_before_message(Conversation? conversation, DateTime before, int id, int count = 20) { // SortedSet? before = messages[conversation].head_set(message); // if (before != null && before.size >= count) { // Gee.List ret = new ArrayList(Message.equals_func); // Iterator iter = before.iterator(); // iter.next(); // for (int from_index = before.size - count; iter.has_next() && from_index > 0; from_index--) iter.next(); // while(iter.has_next()) { // Message m = iter.get(); // ret.add(m); // iter.next(); // } // return ret; // } else { Gee.List db_messages = db.get_messages(conversation.counterpart, conversation.account, Util.get_message_type_for_conversation(conversation), count, before, null, id); Gee.List ret = new ArrayList(); foreach (Message message in db_messages) { ret.add(new MessageItem(message, conversation, -1)); } return ret; // } } public Gee.List get_messages_after_message(Conversation? conversation, DateTime after, int id, int count = 20) { Gee.List db_messages = db.get_messages(conversation.counterpart, conversation.account, Util.get_message_type_for_conversation(conversation), count, null, after, id); Gee.List ret = new ArrayList(); foreach (Message message in db_messages) { ret.add(new MessageItem(message, conversation, -1)); } return ret; } public Message? get_message_by_id(int id, Conversation conversation) { init_conversation(conversation); foreach (Message message in messages[conversation]) { if (message.id == id) return message; } return null; } public Message? get_message_by_stanza_id(string stanza_id, Conversation conversation) { init_conversation(conversation); foreach (Message message in messages[conversation]) { if (message.stanza_id == stanza_id) return message; } return null; } public Conversation? get_conversation_for_stanza_id(Account account, string stanza_id) { foreach (Conversation conversation in messages.keys) { if (!conversation.account.equals(account)) continue; foreach (Message message in messages[conversation]) { if (message.stanza_id == stanza_id) return conversation; } } return null; } private void init_conversation(Conversation conversation) { if (!messages.has_key(conversation)) { messages[conversation] = new Gee.TreeSet((a, b) => { int res = a.local_time.compare(b.local_time); if (res == 0) { res = a.time.compare(b.time); } if (res == 0) { res = a.id - b.id > 0 ? 1 : -1; } return res; }); Gee.List db_messages = db.get_messages(conversation.counterpart, conversation.account, Util.get_message_type_for_conversation(conversation), 50, null, null, -1); messages[conversation].add_all(db_messages); } } } }