⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 messagequeue.java

📁 java写的qq代码实现qq的部分功能
💻 JAVA
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.ListIterator;

import edu.tsinghua.lumaqq.models.ClusterIdMatcher;
import edu.tsinghua.lumaqq.models.QQNumberMatcher;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.packets.BasicInPacket;
import edu.tsinghua.lumaqq.qq.packets.in.ReceiveIMPacket;
import edu.tsinghua.swt.models.ShutterModel;
import edu.tsinghua.swt.widgets.CoolButton;

/**
 * 消息队列实现类
 * 
 *  * @author 马若劼
 */
public class MessageQueue {
	// 总队列
	private LinkedList queue;
	// 系统消息队列
	private LinkedList sysQueue;
	// 延迟处理队列
	private LinkedList postponeQueue;
	// 用户消息队列映射哈希表
	private Hashtable userQueueMap; 
	// 短消息队列
	private LinkedList smsQueue;
	// shutter model,需要有model才好判断哪个好友是哪个组的
	private ShutterModel model;
	// QQ号码匹配器
	private QQNumberMatcher qqNumMatcher;
	// 群内部ID匹配器
	private ClusterIdMatcher clusterIdMatcher;
	
	private static MessageQueue instance = new MessageQueue();
	
	public static MessageQueue getInstance() {
		return instance;
	}
	
	/**
	 * 私有构造函数,singleton模式 
	 */
	private MessageQueue() {
		queue = new LinkedList();
		sysQueue = new LinkedList();
		postponeQueue = new LinkedList();
		userQueueMap = new Hashtable();
		smsQueue = new LinkedList();
		qqNumMatcher = new QQNumberMatcher();
		clusterIdMatcher = new ClusterIdMatcher();
	}
	
	/**
	 * 情况所有数据
	 */
	public void clear() {
		queue.clear();
		sysQueue.clear();
		postponeQueue.clear();
		userQueueMap.clear();
	}
	
	/**
	 * 设置model
	 * @param model
	 */
	public void setModel(ShutterModel model) {
		this.model = model;
	}

	/**
	 * 得到下一条某个好友发来的消息,但是不把它从队列中删除
	 * @param qqNum 好友QQ号
	 * @return 如果有消息则返回消息,否则返回null
	 */
	public BasicInPacket peekMessage(int qqNum) {
		Integer qq = new Integer(qqNum);
		if(userQueueMap.containsKey(qq)) {
			LinkedList userQueue = (LinkedList)userQueueMap.get(qq);
			if(userQueue.size() > 0)
				return (BasicInPacket)userQueue.getFirst();
			else
				return null;
		} else
			return null;
	}
	
	/**
	 * 得到第一条短消息,但是不把它从队列中删除
	 * 
	 * @return InPacket对象,如果队列为空,返回null
	 */
	public BasicInPacket peekSMS() {
	    if(smsQueue.size() > 0)
	        return (BasicInPacket)smsQueue.getFirst();
	    else
	        return null;
	}
	
	/**
	 * 添加一个短消息到队列末尾
	 * 
	 * @param in
	 */
	public void putSMS(BasicInPacket in) {
	    if(in != null) {
	        smsQueue.addLast(in);
	        queue.addLast(in);
	    }
	}
	
	/**
	 * 得到队列中第一条短消息,并且把它从队列中删除
	 * 
	 * @return InPacket,如果队列为空,返回null
	 */
	public BasicInPacket getSMS() {
	    if(smsQueue.size() > 0) {
	        BasicInPacket in = (BasicInPacket)smsQueue.removeFirst();
	        queue.remove(in);
	        return in;
	    } else
	        return null;
	}
	
	/**
	 * 得到下一条某组的消息,但是不把它从队列中删除
	 * @param g 组索引
	 * @return 如果有消息则返回消息,否则返回null
	 */
	public BasicInPacket peekGroupMessage(int g) {
		int nextSender = nextGroupSender(g);
		if(nextSender == -1)
			return null;
		else {
			Integer key = new Integer(nextSender);
			LinkedList userQueue = (LinkedList)userQueueMap.get(key);
			return (BasicInPacket)userQueue.getFirst();
		}
	}
	
	/**
	 * 得到下一条系统消息,但是不把他从队列中删除
	 * @return 如果有消息则返回消息,否则返回null
	 */
	public BasicInPacket peekSystemMessage() {
		if(sysQueue.size() > 0)
			return (BasicInPacket)sysQueue.getFirst();
		else
			return null;
	}

	/**
	 * 把一个普通消息包推入消息队列
	 * @param packet 
	 * 		消息包对象
	 * @param group 
	 * 		CoolButton对象,之所以用这个,是因为索引是可能变化的
	 */
	public void putMessage(BasicInPacket packet, CoolButton group) {
		putMessage(packet, group, true);
	}
	
	/**
	 * @param packet 
	 * 		消息包对象
	 * @param group 
	 * 		CoolButton对象,之所以用这个,是因为索引是可能变化的
	 * @param global
	 * 		true表示添加这个消息到总队列中
	 */
	public void putMessage(BasicInPacket packet, CoolButton group, boolean global) {
		ReceiveIMPacket im = (ReceiveIMPacket)packet;
		
		// 得到QQ号,判断是否已经存在该用户的消息队列,如果这个是群消息,这个其实就是群的内部ID
		Integer qq = null;
		if(im.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
		    qq = new Integer(im.clusterIM.clusterId);
		else
		    qq = new Integer(im.header.sender);
		LinkedList userQueue = null;
		if(!userQueueMap.containsKey(qq)) {
			userQueue = new LinkedList();
			userQueueMap.put(qq, userQueue);
		} else {
			userQueue = (LinkedList)userQueueMap.get(qq);
		}
		// 消息推入用户队列组队列和总队列
		userQueue.addLast(packet);
		if(global)
			queue.addLast(packet);
	}

	/**
	 * 把一个系统消息推入队列
	 * @param packet
	 */
	public void putSystemMessage(BasicInPacket packet) {
		sysQueue.addLast(packet);
		queue.addLast(packet);
	}

	/**
	 * 得到一条普通消息,并把他从队列中删除
	 * @param qqNum 发送消息的好友QQ号
	 * @return 如果有消息在返回消息,否则返回null
	 */
	public BasicInPacket getMessage(int qqNum) {
		Integer qq = new Integer(qqNum);
		return getMessage(qq);
	}
	
	/**
	 * 得到一条普通消息,并把他从队列中删除
	 * @param qq 发送消息的好友QQ号的Integer形式,如果是群,其实就是内部ID
	 * @return 如果有消息在返回消息,否则返回null
	 */
	public BasicInPacket getMessage(Integer qq) {
		// 检查是否有这个队列,有则取第一个消息,如果取后队列为空,删除这个队列
		if(userQueueMap.containsKey(qq)) {
			LinkedList userQueue = (LinkedList)userQueueMap.get(qq);
			if(userQueue.size() == 0) return null;
			BasicInPacket p = (BasicInPacket)userQueue.removeFirst();
			// 从总队列中删除
			queue.remove(p);
			// 如果用户消息队列为空,删除这个队列,为什么我不判断组队列为不为空并删除呢?
			//     主要我是觉得组往往是少数,而好友多的可能有几百个,如果不删除队列的话
			//     可能比较浪费内存
			if(userQueue.size() == 0) {
				userQueueMap.remove(qq);
			}
			return p;
		} else
			return null;
	}
	
	/**
	 * 把qq号指定的好友或者群的所有消息删除
	 * @param qq 可能是好友的QQ号,也可能是群的内部ID
	 */
	public void removeMessage(Integer qq) {
		// 检查是否有这个队列
		if(userQueueMap.containsKey(qq)) {
			LinkedList userQueue = (LinkedList)userQueueMap.get(qq);
			ListIterator iter = userQueue.listIterator();
			while(iter.hasNext()) {
				// 从总队列中删除
				Object obj = iter.next();
				queue.remove(obj);
			}
			// 从队列映射表中删除
			userQueueMap.remove(qq);
		}
	}
	
	/**
	 * 把qq号指定的好友或者群的所有消息删除
	 * @param qq 可能是好友的QQ号,也可能是群的内部ID
	 */
	public void removeMessage(int qq) {
		removeMessage(new Integer(qq));
	}
	
	/**
	 * 得到一条普通消息,这条消息是该组内队列的第一条
	 * @param g 组索引
	 * @return 如果有则返回消息,否则返回null
	 */
	public BasicInPacket getGroupMessage(int g) {
		int nextSender = nextGroupSender(g);
		if(nextSender == -1)
			return null;
		else {
			Integer key = new Integer(nextSender);
			LinkedList userQueue = (LinkedList)userQueueMap.get(key);
			return (BasicInPacket)userQueue.removeFirst();
		}
	}

	/**
	 * 得到一条系统消息,并把他从队列删除
	 * @return 如果有消息,返回消息,否则返回null
	 */
	public BasicInPacket getSystemMessage() {
		if(sysQueue.size() > 0) {
			BasicInPacket p = (BasicInPacket)sysQueue.removeFirst();
			queue.remove(p);
			return p;
		} else
			return null;
	}

	/**
	 * 检查是否某个好友还有消息未读
	 * @param qqNum 好友QQ号
	 * @return true如果有消息未读
	 */
	public boolean hasMessage(int qqNum) {
		Integer qq = new Integer(qqNum);
		return hasMessage(qq);
	}
	
	/**
	 * 检查是否某个好友还有消息未读
	 * @param key 好友QQ号的Integer类
	 * @return true如果有消息未读
	 */
	public boolean hasMessage(Integer key) {
		return userQueueMap.containsKey(key);
	}
	
	/**
	 * 检查某个组是否有消息未读
	 * @param g 组索引
	 * @return true如果有消息未读
	 */
	public boolean hasGroupMessage(int g) {
		return nextGroupSender(g) != -1;
	}

	/**
	 * @return true如果还有任何消息未读
	 */
	public boolean hasNext() {
		return queue.size() > 0;
	}

	/**
	 * @return true如果还有系统消息未读
	 */
	public boolean hasSystemMessage() {
		return sysQueue.size() > 0;
	}
	
	/**
	 * @return true如果还有短消息
	 */
	public boolean hasSMS() {
	    return smsQueue.size() > 0;
	}

	/**
	 * @return 下一条消息的发送者的QQ号,如果是0,表示是系统消息,-1表示无消息
	 *           如果是群消息,返回的将是群的内部ID
	 */
	public int nextSender() {
		if(queue.size() == 0) return -1;
		BasicInPacket packet = (BasicInPacket)queue.getFirst();
		if(packet instanceof ReceiveIMPacket) {
			ReceiveIMPacket im = (ReceiveIMPacket)packet;
			if(im.header.type == QQ.QQ_RECV_IM_SYS_MESSAGE)
				return 0;
			else if(im.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
			    return im.clusterIM.clusterId;
			else
				return im.header.sender;
		} else
			return 0;
	}
	
	/**
	 * 返回下一个消息的来源,对于普通消息,返回QQ_IM_FROM_FRIEND,对于系统消息,返回QQ_IM_FROM_SYS
	 * 对于群消息,有两种情况,因为群消息包含了普通消息和通知消息,对于普通消息,我们返回
	 * QQ_IM_FROM_CLUSTER,对于通知消息,我们返回QQ_IM_FROM_SYS
	 * @return
	 */
	public int nextMessageSource() {
		if(queue.size() == 0) return -1;
		BasicInPacket packet = (BasicInPacket)queue.getFirst();
		if(packet instanceof ReceiveIMPacket) {
			ReceiveIMPacket im = (ReceiveIMPacket)packet;
			if(im.header.type == QQ.QQ_RECV_IM_SYS_MESSAGE)
				return QQ.QQ_IM_FROM_SYS;
			else if(im.header.type == QQ.QQ_RECV_IM_FROM_FRIEND || im.header.type == QQ.QQ_RECV_IM_FROM_STRANGER)
				return QQ.QQ_IM_FROM_USER;
			else if(im.header.type == QQ.QQ_RECV_IM_CLUSTER_IM ||
			        im.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM ||
			        im.header.type == QQ.QQ_RECV_IM_UNKNOWN_CLUSTER_IM)
				return QQ.QQ_IM_FROM_CLUSTER;
			else if(im.header.type == QQ.QQ_RECV_IM_SMS || im.header.type == QQ.QQ_RECV_IM_MOBILE_QQ)
			    return QQ.QQ_IM_FROM_SMS;
			else
				return QQ.QQ_IM_FROM_SYS;
		} else
			return QQ.QQ_IM_FROM_SYS;
	}
	
	/**
	 * 返回该组内下一条消息发送者的QQ号
	 * @param g 组索引
	 * @return QQ号,如果没有消息,返回-1
	 */
	public int nextGroupSender(int g) {
		ListIterator iter = queue.listIterator();
		while(iter.hasNext()) {
			Object obj = iter.next();
			if(obj instanceof ReceiveIMPacket) {
			    ReceiveIMPacket packet = (ReceiveIMPacket)obj;
			    if(packet.header.type == QQ.QQ_RECV_IM_SMS || packet.header.type == QQ.QQ_RECV_IM_MOBILE_QQ) 
			        continue;
				// 得到下一个包的发送者QQ号		
			    int sender = packet.header.sender;
			    if(packet.header.type == QQ.QQ_RECV_IM_TEMP_CLUSTER_IM)
			    	sender = packet.clusterIM.clusterId;
				// 在g指定的组中查找是否有这个好友
				qqNumMatcher.setQQ(sender, true);
				int[] indices = model.findItemIndex(g, qqNumMatcher);
				// 如果有,那么肯定这是下一个发送者,返回
				if(indices != null && indices.length > 0)
					return sender;
				else {
					// 如果没有,看看这个是不是群
					clusterIdMatcher.setClusterId(sender);
					indices = model.findItemIndex(g, clusterIdMatcher);
					if(indices != null && indices.length > 0)
						return sender;
				}
			}
		}
		return -1;
	}
	
	/**
	 * 一个消息在好友列表还没得到之前到达了,延迟处理这个消息
	 * @param packet 消息包
	 */
	public void postponeMessage(BasicInPacket packet) {
		postponeQueue.addLast(packet);
	}
	
	/**
	 * 返回下一个延迟处理的消息
	 * @return 如果有则返回消息,没有返回null
	 */
	public BasicInPacket getPostponedMessage() {
		if(postponeQueue.size() > 0)
			return (BasicInPacket)postponeQueue.removeFirst();
		else
			return null;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -