/******************************************************************************* * Copyright 2012 Tor Hveem * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.ubergeek42.weechat.relay.messagehandler; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ubergeek42.weechat.Buffer; import com.ubergeek42.weechat.HotlistItem; import com.ubergeek42.weechat.relay.RelayMessageHandler; import com.ubergeek42.weechat.relay.protocol.Array; import com.ubergeek42.weechat.relay.protocol.Hdata; import com.ubergeek42.weechat.relay.protocol.HdataEntry; import com.ubergeek42.weechat.relay.protocol.Infolist; import com.ubergeek42.weechat.relay.protocol.RelayObject; import com.ubergeek42.weechat.relay.protocol.RelayObject.WType; /** * Manages a list of buffers present in weechat * * @author thveem <xt@bash.no> * */ public class HotlistManager implements RelayMessageHandler { final private static boolean DEBUG = false; private static Logger logger = LoggerFactory.getLogger("HotlistManager"); ArrayList<HotlistItem> hotlist = new ArrayList<HotlistItem>(); private HotlistManagerObserver onChangeObserver; private BufferManager bufferManager; public void setBufferManager(BufferManager bfm) { this.bufferManager = bfm; } /** * Get the hotlist */ @SuppressWarnings("unchecked") public ArrayList<HotlistItem> getHotlist() { return (ArrayList<HotlistItem>) hotlist.clone(); } public int getSize() { return hotlist.size(); } /** * Register a single observer to be notified when the list of buffers changes * * @param ho * - The observer to receive notifications */ public void onChanged(HotlistManagerObserver ho) { this.onChangeObserver = ho; } /** * Can be called to inform clients that the hotlist have changed in some way */ public void hotlistChanged() { if (onChangeObserver != null) { onChangeObserver.onHotlistChanged(); } } /** * Remove hotlist item from hotlist. Called when switching to the buffer to read the lines * * @param fullBufferName */ public void removeHotlistItem(String fullBufferName) { // HotlistItem hli = null; for (HotlistItem hli : hotlist) { if (hli.getFullName().equals(fullBufferName)) { hotlist.remove(hli); hotlistChanged(); return; } } } @Override public void handleMessage(RelayObject obj, String id) { if (id.equals("_buffer_line_added")) { // New line added...what is it? Hdata hdata = (Hdata) obj; outer: for (int i = 0; i < hdata.getCount(); i++) { HdataEntry hde = hdata.getItem(i); // TODO: check last item of path is line_data // Is line displayed or hidden by filters, etc? boolean displayed = (hde.getItem("displayed").asChar() == 0x01); if (!displayed) { continue; } String bPointer = hde.getItem("buffer").asPointer(); Buffer b = bufferManager.findByPointer(bPointer); if (b == null) { // No buffer associated with this line continue; } // TODO Check for buffer type // Ignore core / server, etc // Try to get the array tags (added in 0.3.9-dev: 2012-07-23) RelayObject tags = hde.getItem("tags_array"); if (tags != null && tags.getType() == WType.ARR) { Array tagsArray = tags.asArray(); int tagCount = tagsArray.length(); if (tagCount == 0) { // All important messages have tags if (DEBUG) logger.debug("handleMessage(): found no tags in buffer '{}', ,skipping line.", b.getFullName()); continue; } for (int ai = 0; ai < tagCount; ai++) { String tag = tagsArray.get(ai).asString(); if (tag.equals("irc_smart_filter") || tag.equals("irc_mode") || tag.equals("irc_quit") || tag.equals("irc_join") || tag.equals("notify_none")) { if (DEBUG) logger.debug("handleMessage(): found tag: '{}', skipping line.", tag); continue outer; } } } HotlistItem hli = new HotlistItem(hde, b); boolean found = false; for (HotlistItem oldhli : hotlist) { // FIXME implement comparator ? if (oldhli.getFullName().equals(hli.getFullName())) { oldhli.count00 += hli.count00; oldhli.count01 += hli.count01; oldhli.count02 += hli.count02; oldhli.count03 += hli.count03; found = true; break; } } // Only add to hotlist if there are actual messages if (!found && (hli.getHighlights() > 0 || hli.getUnread() > 0)) { hotlist.add(hli); } } } else { Infolist infolist = (Infolist) obj; hotlist.clear(); for (int i = 0; i < infolist.size(); i++) { HashMap<String, RelayObject> item = infolist.getItem(i); HotlistItem hli = new HotlistItem(item); // Sync the initial counts to the buffers too Buffer b = bufferManager.findByPointer(hli.buffer); if (b != null) { b.addHighlights(hli.getHighlights()); b.addUnreads(hli.getUnread()); } // Only add messages and highlights to hotlist // TODO: this could be a preference if (hli.count01 > 0 || hli.count02 > 0) { // We got count, check and see if we already have buffer in hotlist hotlist.add(hli); if (b != null) { // FIXME this could probably only be signaled once bufferManager.buffersChanged(); } } } } // Sort the hotlist, highlights first, then unread Collections.sort(hotlist, new Comparator<HotlistItem>() { @Override public int compare(HotlistItem b1, HotlistItem b2) { int b1Highlights = b1.getHighlights(); int b2Highlights = b2.getHighlights(); if (b2Highlights > 0 || b1Highlights > 0) { return b2Highlights - b1Highlights; } return b1.bufferNumber - b2.bufferNumber; } }); // FIXME We probably changed, but this could be more intelligent hotlistChanged(); } }