mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-11 10:09:38 +02:00
Created new chat manager which handles the creation of Chats.
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@6213 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
18a35e4e8f
commit
ae6065d7cc
36 changed files with 3964 additions and 714 deletions
|
@ -20,15 +20,12 @@
|
|||
|
||||
package org.jivesoftware.smack;
|
||||
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.ThreadFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* A chat is a series of messages sent between two users. Each chat has a unique
|
||||
|
@ -37,73 +34,28 @@ import java.util.Set;
|
|||
* don't send thread IDs at all. Therefore, if a message without a thread ID
|
||||
* arrives it is routed to the most recently created Chat with the message
|
||||
* sender.
|
||||
*
|
||||
* @see XMPPConnection#createChat(String)
|
||||
*
|
||||
* @author Matt Tucker
|
||||
*/
|
||||
public class Chat {
|
||||
|
||||
/**
|
||||
* A prefix helps to make sure that ID's are unique across mutliple instances.
|
||||
*/
|
||||
private static String prefix = StringUtils.randomString(5);
|
||||
|
||||
/**
|
||||
* Keeps track of the current increment, which is appended to the prefix to
|
||||
* forum a unique ID.
|
||||
*/
|
||||
private static long id = 0;
|
||||
|
||||
/**
|
||||
* Returns the next unique id. Each id made up of a short alphanumeric
|
||||
* prefix along with a unique numeric value.
|
||||
*
|
||||
* @return the next id.
|
||||
*/
|
||||
private static synchronized String nextID() {
|
||||
return prefix + Long.toString(id++);
|
||||
}
|
||||
|
||||
private XMPPConnection connection;
|
||||
private ChatManager chatManager;
|
||||
private String threadID;
|
||||
private String participant;
|
||||
private PacketFilter messageFilter;
|
||||
private PacketCollector messageCollector;
|
||||
private final Set<WeakReference<PacketListener>> listeners =
|
||||
new HashSet<WeakReference<PacketListener>>();
|
||||
|
||||
/**
|
||||
* Creates a new chat with the specified user.
|
||||
*
|
||||
* @param connection the connection the chat will use.
|
||||
* @param participant the user to chat with.
|
||||
*/
|
||||
public Chat(XMPPConnection connection, String participant) {
|
||||
// Automatically assign the next chat ID.
|
||||
this(connection, participant, nextID());
|
||||
}
|
||||
new CopyOnWriteArraySet<WeakReference<PacketListener>>();
|
||||
|
||||
/**
|
||||
* Creates a new chat with the specified user and thread ID.
|
||||
*
|
||||
* @param connection the connection the chat will use.
|
||||
* @param chatManager the chatManager the chat will use.
|
||||
* @param participant the user to chat with.
|
||||
* @param threadID the thread ID to use.
|
||||
*/
|
||||
public Chat(XMPPConnection connection, String participant, String threadID) {
|
||||
this.connection = connection;
|
||||
Chat(ChatManager chatManager, String participant, String threadID) {
|
||||
this.chatManager = chatManager;
|
||||
this.participant = participant;
|
||||
this.threadID = threadID;
|
||||
|
||||
// Register with the map of chats so that messages with no thread ID
|
||||
// set will be delivered to this Chat.
|
||||
connection.chats.put(StringUtils.parseBareAddress(participant),
|
||||
new WeakReference<Chat>(this));
|
||||
|
||||
// Filter the messages whose thread equals Chat's id
|
||||
messageFilter = new ThreadFilter(threadID);
|
||||
|
||||
messageCollector = connection.createPacketCollector(messageFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,30 +92,15 @@ public class Chat {
|
|||
* @throws XMPPException if sending the message fails.
|
||||
*/
|
||||
public void sendMessage(String text) throws XMPPException {
|
||||
Message message = createMessage();
|
||||
message.setBody(text);
|
||||
connection.sendPacket(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Message to the chat participant. The message returned
|
||||
* will have its thread property set with this chat ID.
|
||||
*
|
||||
* @return a new message addressed to the chat participant and
|
||||
* using the correct thread value.
|
||||
* @see #sendMessage(Message)
|
||||
*/
|
||||
public Message createMessage() {
|
||||
Message message = new Message(participant, Message.Type.CHAT);
|
||||
Message message = new Message(participant, Message.Type.chat);
|
||||
message.setThread(threadID);
|
||||
return message;
|
||||
message.setBody(text);
|
||||
chatManager.sendMessage(this, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the other chat participant. The thread ID, recipient,
|
||||
* and message type of the message will automatically set to those of this chat
|
||||
* in case the Message was not created using the {@link #createMessage() createMessage}
|
||||
* method.
|
||||
* and message type of the message will automatically set to those of this chat.
|
||||
*
|
||||
* @param message the message to send.
|
||||
* @throws XMPPException if an error occurs sending the message.
|
||||
|
@ -172,47 +109,9 @@ public class Chat {
|
|||
// Force the recipient, message type, and thread ID since the user elected
|
||||
// to send the message through this chat object.
|
||||
message.setTo(participant);
|
||||
message.setType(Message.Type.CHAT);
|
||||
message.setType(Message.Type.chat);
|
||||
message.setThread(threadID);
|
||||
connection.sendPacket(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls for and returns the next message, or <tt>null</tt> if there isn't
|
||||
* a message immediately available. This method provides significantly different
|
||||
* functionalty than the {@link #nextMessage()} method since it's non-blocking.
|
||||
* In other words, the method call will always return immediately, whereas the
|
||||
* nextMessage method will return only when a message is available (or after
|
||||
* a specific timeout).
|
||||
*
|
||||
* @return the next message if one is immediately available and
|
||||
* <tt>null</tt> otherwise.
|
||||
*/
|
||||
public Message pollMessage() {
|
||||
return (Message)messageCollector.pollResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available message in the chat. The method call will block
|
||||
* (not return) until a message is available.
|
||||
*
|
||||
* @return the next message.
|
||||
*/
|
||||
public Message nextMessage() {
|
||||
return (Message)messageCollector.nextResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available message in the chat. The method call will block
|
||||
* (not return) until a packet is available or the <tt>timeout</tt> has elapased.
|
||||
* If the timeout elapses without a result, <tt>null</tt> will be returned.
|
||||
*
|
||||
* @param timeout the maximum amount of time to wait for the next message.
|
||||
* @return the next message, or <tt>null</tt> if the timeout elapses without a
|
||||
* message becoming available.
|
||||
*/
|
||||
public Message nextMessage(long timeout) {
|
||||
return (Message)messageCollector.nextResult(timeout);
|
||||
chatManager.sendMessage(this, message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,12 +121,21 @@ public class Chat {
|
|||
* @param listener a packet listener.
|
||||
*/
|
||||
public void addMessageListener(PacketListener listener) {
|
||||
connection.addPacketListener(listener, messageFilter);
|
||||
// Keep track of the listener so that we can manually deliver extra
|
||||
// messages to it later if needed.
|
||||
synchronized (listeners) {
|
||||
listeners.add(new WeakReference<PacketListener>(listener));
|
||||
if(listener == null) {
|
||||
return;
|
||||
}
|
||||
listeners.add(new WeakReference<PacketListener>(listener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link org.jivesoftware.smack.PacketCollector} which will accumulate the Messages
|
||||
* for this chat. Always cancel PacketCollectors when finished with them as they will accumulate
|
||||
* messages indefinitely.
|
||||
*
|
||||
* @return the PacketCollector which returns Messages for this chat.
|
||||
*/
|
||||
public PacketCollector createCollector() {
|
||||
return chatManager.createPacketCollector(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,31 +152,16 @@ public class Chat {
|
|||
// probably never had one.
|
||||
message.setThread(threadID);
|
||||
|
||||
messageCollector.processPacket(message);
|
||||
synchronized (listeners) {
|
||||
for (Iterator<WeakReference<PacketListener>> i=listeners.iterator(); i.hasNext(); ) {
|
||||
WeakReference<PacketListener> listenerRef = i.next();
|
||||
PacketListener listener;
|
||||
if ((listener = listenerRef.get()) != null) {
|
||||
listener.processPacket(message);
|
||||
}
|
||||
// If the reference was cleared, remove it from the set.
|
||||
else {
|
||||
i.remove();
|
||||
}
|
||||
for (Iterator<WeakReference<PacketListener>> i = listeners.iterator(); i.hasNext();) {
|
||||
WeakReference<PacketListener> listenerRef = i.next();
|
||||
PacketListener listener;
|
||||
if ((listener = listenerRef.get()) != null) {
|
||||
listener.processPacket(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
try {
|
||||
if (messageCollector != null) {
|
||||
messageCollector.cancel();
|
||||
// If the reference was cleared, remove it from the set.
|
||||
else {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Ignore.
|
||||
}
|
||||
}
|
||||
}
|
25
source/org/jivesoftware/smack/ChatListener.java
Normal file
25
source/org/jivesoftware/smack/ChatListener.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* $RCSfile: $
|
||||
* $Revision: $
|
||||
* $Date: $
|
||||
*
|
||||
* Copyright (C) 2006 Jive Software. All rights reserved.
|
||||
* This software is the proprietary information of Jive Software. Use is subject to license terms.
|
||||
*/
|
||||
package org.jivesoftware.smack;
|
||||
|
||||
/**
|
||||
* A listener for chat related events.
|
||||
*
|
||||
* @author Alexander Wenckus
|
||||
*/
|
||||
public interface ChatListener {
|
||||
|
||||
/**
|
||||
* Event fired when a new chat is created.
|
||||
*
|
||||
* @param chat the chat that was created.
|
||||
* @param createdLocally true if the chat was created by the local user and false if it wasn't.
|
||||
*/
|
||||
void chatCreated(Chat chat, boolean createdLocally);
|
||||
}
|
188
source/org/jivesoftware/smack/ChatManager.java
Normal file
188
source/org/jivesoftware/smack/ChatManager.java
Normal file
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* $RCSfile: $
|
||||
* $Revision: $
|
||||
* $Date: $
|
||||
*
|
||||
* Copyright (C) 2006 Jive Software. All rights reserved.
|
||||
* This software is the proprietary information of Jive Software. Use is subject to license terms.
|
||||
*/
|
||||
package org.jivesoftware.smack;
|
||||
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.collections.ReferenceMap;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.filter.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* The chat manager keeps track of references to all current chats. It will not hold any references
|
||||
* in memory on its own so it is neccesary to keep a reference to the chat object itself. To be
|
||||
* made aware of new chats, register a listener by calling {@link #addChatListener(ChatListener)}.
|
||||
*
|
||||
* @author Alexander Wenckus
|
||||
*/
|
||||
public class ChatManager {
|
||||
/**
|
||||
* Returns the next unique id. Each id made up of a short alphanumeric
|
||||
* prefix along with a unique numeric value.
|
||||
*
|
||||
* @return the next id.
|
||||
*/
|
||||
private static synchronized String nextID() {
|
||||
return prefix + Long.toString(id++);
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix helps to make sure that ID's are unique across mutliple instances.
|
||||
*/
|
||||
private static String prefix = StringUtils.randomString(5);
|
||||
|
||||
/**
|
||||
* Keeps track of the current increment, which is appended to the prefix to
|
||||
* forum a unique ID.
|
||||
*/
|
||||
private static long id = 0;
|
||||
|
||||
/**
|
||||
* Maps thread ID to chat.
|
||||
*/
|
||||
private Map<String, Chat> threadChats = new ReferenceMap<String, Chat>(ReferenceMap.HARD,
|
||||
ReferenceMap.WEAK);
|
||||
|
||||
/**
|
||||
* Maps jids to chats
|
||||
*/
|
||||
private Map<String, Chat> jidChats = new ReferenceMap<String, Chat>(ReferenceMap.HARD,
|
||||
ReferenceMap.WEAK);
|
||||
|
||||
private Set<ChatListener> chatListeners = new CopyOnWriteArraySet<ChatListener>();
|
||||
|
||||
private XMPPConnection connection;
|
||||
|
||||
ChatManager(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
|
||||
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class),
|
||||
new PacketFilter() {
|
||||
|
||||
public boolean accept(Packet packet) {
|
||||
if (!(packet instanceof Message)) {
|
||||
return false;
|
||||
}
|
||||
Message.Type messageType = ((Message) packet).getType();
|
||||
return messageType != Message.Type.groupchat &&
|
||||
messageType != Message.Type.headline;
|
||||
}
|
||||
});
|
||||
// Add a listener for all message packets so that we can deliver errant
|
||||
// messages to the best Chat instance available.
|
||||
connection.addPacketListener(new PacketListener() {
|
||||
public void processPacket(Packet packet) {
|
||||
Message message = (Message) packet;
|
||||
Chat chat;
|
||||
if (message.getThread() == null) {
|
||||
chat = getUserChat(StringUtils.parseBareAddress(message.getFrom()));
|
||||
}
|
||||
else {
|
||||
chat = getThreadChat(message.getThread());
|
||||
}
|
||||
|
||||
if(chat == null) {
|
||||
chat = createChat(message);
|
||||
}
|
||||
deliverMessage(chat, message);
|
||||
}
|
||||
}, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new chat and returns it.
|
||||
*
|
||||
* @param userJID the user this chat is with.
|
||||
* @param listener the listener which will listen for new messages from this chat.
|
||||
* @return the created chat.
|
||||
*/
|
||||
public Chat createChat(String userJID, PacketListener listener) {
|
||||
String threadID = nextID();
|
||||
|
||||
Chat chat = createChat(userJID, threadID, true);
|
||||
chat.addMessageListener(listener);
|
||||
|
||||
return chat;
|
||||
}
|
||||
|
||||
private Chat createChat(String userJID, String threadID, boolean createdLocally) {
|
||||
Chat chat = new Chat(this, userJID, threadID);
|
||||
threadChats.put(threadID, chat);
|
||||
jidChats.put(userJID, chat);
|
||||
|
||||
for(ChatListener listener : chatListeners) {
|
||||
listener.chatCreated(chat, createdLocally);
|
||||
}
|
||||
|
||||
return chat;
|
||||
}
|
||||
|
||||
private Chat createChat(Message message) {
|
||||
String threadID = message.getThread();
|
||||
String userJID = message.getFrom();
|
||||
|
||||
return createChat(userJID, threadID, false);
|
||||
}
|
||||
|
||||
private Chat getUserChat(String userJID) {
|
||||
return jidChats.get(userJID);
|
||||
}
|
||||
|
||||
private Chat getThreadChat(String thread) {
|
||||
return threadChats.get(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new listener with the ChatManager to recieve events related to chats.
|
||||
*
|
||||
* @param listener the listener.
|
||||
*/
|
||||
public void addChatListener(ChatListener listener) {
|
||||
chatListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener, it will no longer be notified of new events related to chats.
|
||||
*
|
||||
* @param listener the listener that is being removed
|
||||
*/
|
||||
public void removeChatListener(ChatListener listener) {
|
||||
chatListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable collection of all chat listeners currently registered with this
|
||||
* manager.
|
||||
*
|
||||
* @return an unmodifiable collection of all chat listeners currently registered with this
|
||||
* manager.
|
||||
*/
|
||||
public Collection<ChatListener> getChatListeners() {
|
||||
return Collections.unmodifiableCollection(chatListeners);
|
||||
}
|
||||
|
||||
private void deliverMessage(Chat chat, Message message) {
|
||||
// Here we will run any interceptors
|
||||
chat.deliver(message);
|
||||
}
|
||||
|
||||
void sendMessage(Chat chat, Message message) {
|
||||
// Here we will run any interceptors
|
||||
connection.sendPacket(message);
|
||||
}
|
||||
|
||||
PacketCollector createPacketCollector(Chat chat) {
|
||||
return connection.createPacketCollector(new AndFilter(new ThreadFilter(chat.getThreadID()),
|
||||
new FromContainsFilter(chat.getParticipant())));
|
||||
}
|
||||
|
||||
}
|
|
@ -22,8 +22,6 @@ package org.jivesoftware.smack;
|
|||
|
||||
import org.jivesoftware.smack.debugger.SmackDebugger;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
|
@ -34,15 +32,12 @@ import javax.net.SocketFactory;
|
|||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.io.*;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
|
@ -147,14 +142,6 @@ public class XMPPConnection {
|
|||
Writer writer;
|
||||
Reader reader;
|
||||
|
||||
/**
|
||||
* A map between JIDs and the most recently created Chat object with that JID.
|
||||
* Reference to the Chat is stored via a WeakReference so that the map
|
||||
* does not interfere with garbage collection. The map of chats must be stored
|
||||
* with each connection.
|
||||
*/
|
||||
Map<String, WeakReference<Chat>> chats = new ConcurrentHashMap<String, WeakReference<Chat>>();
|
||||
|
||||
/**
|
||||
* Collection of available stream compression methods offered by the server.
|
||||
*/
|
||||
|
@ -167,6 +154,7 @@ public class XMPPConnection {
|
|||
* Holds the initial configuration used while creating the connection.
|
||||
*/
|
||||
private ConnectionConfiguration configuration;
|
||||
private ChatManager chatManager;
|
||||
|
||||
/**
|
||||
* Creates a new connection to the specified XMPP server. A DNS SRV lookup will be
|
||||
|
@ -564,18 +552,16 @@ public class XMPPConnection {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new chat with the specified participant. The participant should
|
||||
* be a valid XMPP user such as <tt>jdoe@jivesoftware.com</tt> or
|
||||
* <tt>jdoe@jivesoftware.com/work</tt>.
|
||||
* Returns a chat manager instance for this connection. The ChatManager manages all incoming and
|
||||
* outgoing chats on the current connection.
|
||||
*
|
||||
* @param participant the person to start the conversation with.
|
||||
* @return a new Chat object.
|
||||
* @return a chat manager instance for this connection.
|
||||
*/
|
||||
public Chat createChat(String participant) {
|
||||
if (!isConnected()) {
|
||||
throw new IllegalStateException("Not connected to server.");
|
||||
public synchronized ChatManager getChatManager() {
|
||||
if(this.chatManager == null) {
|
||||
this.chatManager = new ChatManager(this);
|
||||
}
|
||||
return new Chat(this, participant);
|
||||
return this.chatManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -934,34 +920,6 @@ public class XMPPConnection {
|
|||
for (ConnectionCreationListener listener : connectionEstablishedListeners) {
|
||||
listener.connectionCreated(this);
|
||||
}
|
||||
|
||||
// Add a listener for all message packets so that we can deliver errant
|
||||
// messages to the best Chat instance available.
|
||||
addPacketListener(new PacketListener() {
|
||||
public void processPacket(Packet packet) {
|
||||
Message message = (Message) packet;
|
||||
// Ignore any messages with a thread ID, as they will likely
|
||||
// already be associated with a Chat. This will miss messages
|
||||
// with new thread ID values, but we can only assume that a
|
||||
// listener is registered to deal with this case.
|
||||
if (message.getThread() == null &&
|
||||
message.getType() != Message.Type.GROUP_CHAT &&
|
||||
message.getType() != Message.Type.HEADLINE) {
|
||||
WeakReference<Chat> chatRef =
|
||||
chats.get(StringUtils.parseBareAddress(message.getFrom()));
|
||||
if (chatRef != null) {
|
||||
// Do some extra clean-up if the reference was cleared.
|
||||
Chat chat = chatRef.get();
|
||||
if (chat == null) {
|
||||
chats.remove(message.getFrom());
|
||||
}
|
||||
else {
|
||||
chat.deliver(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, new PacketTypeFilter(Message.class));
|
||||
}
|
||||
else {
|
||||
packetReader.notifyReconnection();
|
||||
|
|
|
@ -22,6 +22,9 @@ package org.jivesoftware.smack.filter;
|
|||
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Implements the logical AND operation over two or more packet filters.
|
||||
* In other words, packets pass this filter if they pass <b>all</b> of the filters.
|
||||
|
@ -30,39 +33,34 @@ import org.jivesoftware.smack.packet.Packet;
|
|||
*/
|
||||
public class AndFilter implements PacketFilter {
|
||||
|
||||
/**
|
||||
* The current number of elements in the filter.
|
||||
*/
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* The list of filters.
|
||||
*/
|
||||
private PacketFilter [] filters;
|
||||
private List<PacketFilter> filters = new ArrayList<PacketFilter>();
|
||||
|
||||
/**
|
||||
* Creates an empty AND filter. Filters should be added using the
|
||||
* {@link #addFilter(PacketFilter)} method.
|
||||
*/
|
||||
public AndFilter() {
|
||||
size = 0;
|
||||
filters = new PacketFilter[3];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AND filter using the two specified filters.
|
||||
* Creates an AND filter using the specified filters.
|
||||
*
|
||||
* @param filter1 the first packet filter.
|
||||
* @param filter2 the second packet filter.
|
||||
* @param filters the filters to add.
|
||||
*/
|
||||
public AndFilter(PacketFilter filter1, PacketFilter filter2) {
|
||||
if (filter1 == null || filter2 == null) {
|
||||
throw new IllegalArgumentException("Parameters cannot be null.");
|
||||
public AndFilter(PacketFilter... filters) {
|
||||
if (filters == null) {
|
||||
throw new IllegalArgumentException("Parameter cannot be null.");
|
||||
}
|
||||
for(PacketFilter filter : filters) {
|
||||
if(filter == null) {
|
||||
throw new IllegalArgumentException("Parameter cannot be null.");
|
||||
}
|
||||
this.filters.add(filter);
|
||||
}
|
||||
size = 2;
|
||||
filters = new PacketFilter[2];
|
||||
filters[0] = filter1;
|
||||
filters[1] = filter2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,22 +73,12 @@ public class AndFilter implements PacketFilter {
|
|||
if (filter == null) {
|
||||
throw new IllegalArgumentException("Parameter cannot be null.");
|
||||
}
|
||||
// If there is no more room left in the filters array, expand it.
|
||||
if (size == filters.length) {
|
||||
PacketFilter [] newFilters = new PacketFilter[filters.length+2];
|
||||
for (int i=0; i<filters.length; i++) {
|
||||
newFilters[i] = filters[i];
|
||||
}
|
||||
filters = newFilters;
|
||||
}
|
||||
// Add the new filter to the array.
|
||||
filters[size] = filter;
|
||||
size++;
|
||||
filters.add(filter);
|
||||
}
|
||||
|
||||
public boolean accept(Packet packet) {
|
||||
for (int i=0; i<size; i++) {
|
||||
if (!filters[i].accept(packet)) {
|
||||
for (PacketFilter filter : filters) {
|
||||
if (!filter.accept(packet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,6 @@ public class ThreadFilter implements PacketFilter {
|
|||
}
|
||||
|
||||
public boolean accept(Packet packet) {
|
||||
if (packet instanceof Message) {
|
||||
return thread.equals(((Message)packet).getThread());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return packet instanceof Message && thread.equals(((Message) packet).getThread());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ import org.jivesoftware.smack.util.StringUtils;
|
|||
*/
|
||||
public class Message extends Packet {
|
||||
|
||||
private Type type = Type.NORMAL;
|
||||
private Type type = Type.normal;
|
||||
private String subject = null;
|
||||
private String body = null;
|
||||
private String thread = null;
|
||||
|
@ -138,7 +138,8 @@ public class Message extends Packet {
|
|||
|
||||
/**
|
||||
* Sets the body of the message. The body is the main message contents.
|
||||
* @param body
|
||||
*
|
||||
* @param body the body of the message.
|
||||
*/
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
|
@ -176,7 +177,7 @@ public class Message extends Packet {
|
|||
if (getFrom() != null) {
|
||||
buf.append(" from=\"").append(StringUtils.escapeForXML(getFrom())).append("\"");
|
||||
}
|
||||
if (type != Type.NORMAL) {
|
||||
if (type != Type.normal) {
|
||||
buf.append(" type=\"").append(type).append("\"");
|
||||
}
|
||||
buf.append(">");
|
||||
|
@ -190,7 +191,7 @@ public class Message extends Packet {
|
|||
buf.append("<thread>").append(thread).append("</thread>");
|
||||
}
|
||||
// Append the error subpacket if the message type is an error.
|
||||
if (type == Type.ERROR) {
|
||||
if (type == Type.error) {
|
||||
XMPPError error = getError();
|
||||
if (error != null) {
|
||||
buf.append(error.toXML());
|
||||
|
@ -205,69 +206,41 @@ public class Message extends Packet {
|
|||
/**
|
||||
* Represents the type of a message.
|
||||
*/
|
||||
public static class Type {
|
||||
public enum Type {
|
||||
|
||||
/**
|
||||
* (Default) a normal text message used in email like interface.
|
||||
*/
|
||||
public static final Type NORMAL = new Type("normal");
|
||||
normal,
|
||||
|
||||
/**
|
||||
* Typically short text message used in line-by-line chat interfaces.
|
||||
*/
|
||||
public static final Type CHAT = new Type("chat");
|
||||
chat,
|
||||
|
||||
/**
|
||||
* Chat message sent to a groupchat server for group chats.
|
||||
*/
|
||||
public static final Type GROUP_CHAT = new Type("groupchat");
|
||||
groupchat,
|
||||
|
||||
/**
|
||||
* Text message to be displayed in scrolling marquee displays.
|
||||
*/
|
||||
public static final Type HEADLINE = new Type("headline");
|
||||
headline,
|
||||
|
||||
/**
|
||||
* indicates a messaging error.
|
||||
*/
|
||||
public static final Type ERROR = new Type("error");
|
||||
error;
|
||||
|
||||
/**
|
||||
* Converts a String value into its Type representation.
|
||||
*
|
||||
* @param type the String value.
|
||||
* @return the Type corresponding to the String.
|
||||
*/
|
||||
public static Type fromString(String type) {
|
||||
if (type == null) {
|
||||
return NORMAL;
|
||||
public static Type fromString(String name) {
|
||||
try {
|
||||
return Type.valueOf(name);
|
||||
}
|
||||
type = type.toLowerCase();
|
||||
if (CHAT.toString().equals(type)) {
|
||||
return CHAT;
|
||||
}
|
||||
else if (GROUP_CHAT.toString().equals(type)) {
|
||||
return GROUP_CHAT;
|
||||
}
|
||||
else if (HEADLINE.toString().equals(type)) {
|
||||
return HEADLINE;
|
||||
}
|
||||
else if (ERROR.toString().equals(type)) {
|
||||
return ERROR;
|
||||
}
|
||||
else {
|
||||
return NORMAL;
|
||||
catch (Exception e) {
|
||||
return normal;
|
||||
}
|
||||
}
|
||||
|
||||
private String value;
|
||||
|
||||
private Type(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Provides an implementation of an empty iterator.
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
abstract class AbstractEmptyIterator <E> {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
protected AbstractEmptyIterator() {
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public E next() {
|
||||
throw new NoSuchElementException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public E previous() {
|
||||
throw new NoSuchElementException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public int nextIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int previousIndex() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void add(E obj) {
|
||||
throw new UnsupportedOperationException("add() not supported for empty Iterator");
|
||||
}
|
||||
|
||||
public void set(E obj) {
|
||||
throw new IllegalStateException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new IllegalStateException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public E getKey() {
|
||||
throw new IllegalStateException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public E getValue() {
|
||||
throw new IllegalStateException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public E setValue(E value) {
|
||||
throw new IllegalStateException("Iterator contains no elements");
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,80 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract pair class to assist with creating KeyValue and MapEntry implementations.
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Michael A. Smith
|
||||
* @author Neil O'Toole
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public abstract class AbstractKeyValue <K,V> implements KeyValue<K, V> {
|
||||
|
||||
/**
|
||||
* The key
|
||||
*/
|
||||
protected K key;
|
||||
/**
|
||||
* The value
|
||||
*/
|
||||
protected V value;
|
||||
|
||||
/**
|
||||
* Constructs a new pair with the specified key and given value.
|
||||
*
|
||||
* @param key the key for the entry, may be null
|
||||
* @param value the value for the entry, may be null
|
||||
*/
|
||||
protected AbstractKeyValue(K key, V value) {
|
||||
super();
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key from the pair.
|
||||
*
|
||||
* @return the key
|
||||
*/
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value from the pair.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a debugging String view of the pair.
|
||||
*
|
||||
* @return a String view of the entry
|
||||
*/
|
||||
public String toString() {
|
||||
return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Abstract Pair class to assist with creating correct Map Entry implementations.
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Michael A. Smith
|
||||
* @author Neil O'Toole
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public abstract class AbstractMapEntry <K,V> extends AbstractKeyValue<K, V> implements Map.Entry<K, V> {
|
||||
|
||||
/**
|
||||
* Constructs a new entry with the given key and given value.
|
||||
*
|
||||
* @param key the key for the entry, may be null
|
||||
* @param value the value for the entry, may be null
|
||||
*/
|
||||
protected AbstractMapEntry(K key, V value) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
// Map.Entry interface
|
||||
//-------------------------------------------------------------------------
|
||||
/**
|
||||
* Sets the value stored in this Map Entry.
|
||||
* <p/>
|
||||
* This Map Entry is not connected to a Map, so only the local data is changed.
|
||||
*
|
||||
* @param value the new value
|
||||
* @return the previous value
|
||||
*/
|
||||
public V setValue(V value) {
|
||||
V answer = this.value;
|
||||
this.value = value;
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this Map Entry with another Map Entry.
|
||||
* <p/>
|
||||
* Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)}
|
||||
*
|
||||
* @param obj the object to compare to
|
||||
* @return true if equal key and value
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Map.Entry == false) {
|
||||
return false;
|
||||
}
|
||||
Map.Entry other = (Map.Entry) obj;
|
||||
return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hashCode compatible with the equals method.
|
||||
* <p/>
|
||||
* Implemented per API documentation of {@link java.util.Map.Entry#hashCode()}
|
||||
*
|
||||
* @return a suitable hash code
|
||||
*/
|
||||
public int hashCode() {
|
||||
return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,65 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2001-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A restricted implementation of {@link java.util.Map.Entry} that prevents
|
||||
* the MapEntry contract from being broken.
|
||||
*
|
||||
* @author James Strachan
|
||||
* @author Michael A. Smith
|
||||
* @author Neil O'Toole
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public final class DefaultMapEntry <K,V> extends AbstractMapEntry<K, V> {
|
||||
|
||||
/**
|
||||
* Constructs a new entry with the specified key and given value.
|
||||
*
|
||||
* @param key the key for the entry, may be null
|
||||
* @param value the value for the entry, may be null
|
||||
*/
|
||||
public DefaultMapEntry(final K key, final V value) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new entry from the specified KeyValue.
|
||||
*
|
||||
* @param pair the pair to copy, must not be null
|
||||
* @throws NullPointerException if the entry is null
|
||||
*/
|
||||
public DefaultMapEntry(final KeyValue<K, V> pair) {
|
||||
super(pair.getKey(), pair.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new entry from the specified MapEntry.
|
||||
*
|
||||
* @param entry the entry to copy, must not be null
|
||||
* @throws NullPointerException if the entry is null
|
||||
*/
|
||||
public DefaultMapEntry(final Map.Entry<K, V> entry) {
|
||||
super(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Provides an implementation of an empty iterator.
|
||||
* <p/>
|
||||
* This class provides an implementation of an empty iterator.
|
||||
* This class provides for binary compatability between Commons Collections
|
||||
* 2.1.1 and 3.1 due to issues with <code>IteratorUtils</code>.
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
|
||||
* @since Commons Collections 2.1.1 and 3.1
|
||||
*/
|
||||
public class EmptyIterator <E> extends AbstractEmptyIterator<E> implements ResettableIterator<E> {
|
||||
|
||||
/**
|
||||
* Singleton instance of the iterator.
|
||||
*
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
public static final ResettableIterator RESETTABLE_INSTANCE = new EmptyIterator();
|
||||
/**
|
||||
* Singleton instance of the iterator.
|
||||
*
|
||||
* @since Commons Collections 2.1.1 and 3.1
|
||||
*/
|
||||
public static final Iterator INSTANCE = RESETTABLE_INSTANCE;
|
||||
|
||||
public static <T> Iterator<T> getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
protected EmptyIterator() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
/**
|
||||
* Provides an implementation of an empty map iterator.
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
public class EmptyMapIterator extends AbstractEmptyIterator implements MapIterator, ResettableIterator {
|
||||
|
||||
/**
|
||||
* Singleton instance of the iterator.
|
||||
*
|
||||
* @since Commons Collections 3.1
|
||||
*/
|
||||
public static final MapIterator INSTANCE = new EmptyMapIterator();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
protected EmptyMapIterator() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Defines a map that can be iterated directly without needing to create an entry set.
|
||||
* <p/>
|
||||
* A map iterator is an efficient way of iterating over maps.
|
||||
* There is no need to access the entry set or cast to Map Entry objects.
|
||||
* <pre>
|
||||
* IterableMap map = new HashedMap();
|
||||
* MapIterator it = map.mapIterator();
|
||||
* while (it.hasNext()) {
|
||||
* Object key = it.next();
|
||||
* Object value = it.getValue();
|
||||
* it.setValue("newValue");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public interface IterableMap <K,V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
* Obtains a <code>MapIterator</code> over the map.
|
||||
* <p/>
|
||||
* A map iterator is an efficient way of iterating over maps.
|
||||
* There is no need to access the entry set or cast to Map Entry objects.
|
||||
* <pre>
|
||||
* IterableMap map = new HashedMap();
|
||||
* MapIterator it = map.mapIterator();
|
||||
* while (it.hasNext()) {
|
||||
* Object key = it.next();
|
||||
* Object value = it.getValue();
|
||||
* it.setValue("newValue");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return a map iterator
|
||||
*/
|
||||
MapIterator<K, V> mapIterator();
|
||||
|
||||
}
|
46
source/org/jivesoftware/smack/util/collections/KeyValue.java
Normal file
46
source/org/jivesoftware/smack/util/collections/KeyValue.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
/**
|
||||
* Defines a simple key value pair.
|
||||
* <p/>
|
||||
* A Map Entry has considerable additional semantics over and above a simple
|
||||
* key-value pair. This interface defines the minimum key value, with just the
|
||||
* two get methods.
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public interface KeyValue <K,V> {
|
||||
|
||||
/**
|
||||
* Gets the key from the pair.
|
||||
*
|
||||
* @return the key
|
||||
*/
|
||||
K getKey();
|
||||
|
||||
/**
|
||||
* Gets the value from the pair.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
V getValue();
|
||||
|
||||
}
|
109
source/org/jivesoftware/smack/util/collections/MapIterator.java
Normal file
109
source/org/jivesoftware/smack/util/collections/MapIterator.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Defines an iterator that operates over a <code>Map</code>.
|
||||
* <p/>
|
||||
* This iterator is a special version designed for maps. It can be more
|
||||
* efficient to use this rather than an entry set iterator where the option
|
||||
* is available, and it is certainly more convenient.
|
||||
* <p/>
|
||||
* A map that provides this interface may not hold the data internally using
|
||||
* Map Entry objects, thus this interface can avoid lots of object creation.
|
||||
* <p/>
|
||||
* In use, this iterator iterates through the keys in the map. After each call
|
||||
* to <code>next()</code>, the <code>getValue()</code> method provides direct
|
||||
* access to the value. The value can also be set using <code>setValue()</code>.
|
||||
* <pre>
|
||||
* MapIterator it = map.mapIterator();
|
||||
* while (it.hasNext()) {
|
||||
* Object key = it.next();
|
||||
* Object value = it.getValue();
|
||||
* it.setValue(newValue);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public interface MapIterator <K,V> extends Iterator<K> {
|
||||
|
||||
/**
|
||||
* Checks to see if there are more entries still to be iterated.
|
||||
*
|
||||
* @return <code>true</code> if the iterator has more elements
|
||||
*/
|
||||
boolean hasNext();
|
||||
|
||||
/**
|
||||
* Gets the next <em>key</em> from the <code>Map</code>.
|
||||
*
|
||||
* @return the next key in the iteration
|
||||
* @throws java.util.NoSuchElementException
|
||||
* if the iteration is finished
|
||||
*/
|
||||
K next();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the current key, which is the key returned by the last call
|
||||
* to <code>next()</code>.
|
||||
*
|
||||
* @return the current key
|
||||
* @throws IllegalStateException if <code>next()</code> has not yet been called
|
||||
*/
|
||||
K getKey();
|
||||
|
||||
/**
|
||||
* Gets the current value, which is the value associated with the last key
|
||||
* returned by <code>next()</code>.
|
||||
*
|
||||
* @return the current value
|
||||
* @throws IllegalStateException if <code>next()</code> has not yet been called
|
||||
*/
|
||||
V getValue();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Removes the last returned key from the underlying <code>Map</code> (optional operation).
|
||||
* <p/>
|
||||
* This method can be called once per call to <code>next()</code>.
|
||||
*
|
||||
* @throws UnsupportedOperationException if remove is not supported by the map
|
||||
* @throws IllegalStateException if <code>next()</code> has not yet been called
|
||||
* @throws IllegalStateException if <code>remove()</code> has already been called
|
||||
* since the last call to <code>next()</code>
|
||||
*/
|
||||
void remove();
|
||||
|
||||
/**
|
||||
* Sets the value associated with the current key (optional operation).
|
||||
*
|
||||
* @param value the new value
|
||||
* @return the previous value
|
||||
* @throws UnsupportedOperationException if setValue is not supported by the map
|
||||
* @throws IllegalStateException if <code>next()</code> has not yet been called
|
||||
* @throws IllegalStateException if <code>remove()</code> has been called since the
|
||||
* last call to <code>next()</code>
|
||||
*/
|
||||
V setValue(V value);
|
||||
|
||||
}
|
161
source/org/jivesoftware/smack/util/collections/ReferenceMap.java
Normal file
161
source/org/jivesoftware/smack/util/collections/ReferenceMap.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2002-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A <code>Map</code> implementation that allows mappings to be
|
||||
* removed by the garbage collector.
|
||||
* <p/>
|
||||
* When you construct a <code>ReferenceMap</code>, you can specify what kind
|
||||
* of references are used to store the map's keys and values.
|
||||
* If non-hard references are used, then the garbage collector can remove
|
||||
* mappings if a key or value becomes unreachable, or if the JVM's memory is
|
||||
* running low. For information on how the different reference types behave,
|
||||
* see {@link java.lang.ref.Reference}.
|
||||
* <p/>
|
||||
* Different types of references can be specified for keys and values.
|
||||
* The keys can be configured to be weak but the values hard,
|
||||
* in which case this class will behave like a
|
||||
* <a href="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
|
||||
* <code>WeakHashMap</code></a>. However, you can also specify hard keys and
|
||||
* weak values, or any other combination. The default constructor uses
|
||||
* hard keys and soft values, providing a memory-sensitive cache.
|
||||
* <p/>
|
||||
* This map is similar to ReferenceIdentityMap.
|
||||
* It differs in that keys and values in this class are compared using <code>equals()</code>.
|
||||
* <p/>
|
||||
* This {@link java.util.Map} implementation does <i>not</i> allow null elements.
|
||||
* Attempting to add a null key or value to the map will raise a <code>NullPointerException</code>.
|
||||
* <p/>
|
||||
* This implementation is not synchronized.
|
||||
* You can use {@link java.util.Collections#synchronizedMap} to
|
||||
* provide synchronized access to a <code>ReferenceMap</code>.
|
||||
* Remember that synchronization will not stop the garbage collecter removing entries.
|
||||
* <p/>
|
||||
* All the available iterators can be reset back to the start by casting to
|
||||
* <code>ResettableIterator</code> and calling <code>reset()</code>.
|
||||
* <p/>
|
||||
* NOTE: As from Commons Collections 3.1 this map extends <code>AbstractReferenceMap</code>
|
||||
* (previously it extended AbstractMap). As a result, the implementation is now
|
||||
* extensible and provides a <code>MapIterator</code>.
|
||||
*
|
||||
* @author Paul Jack
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
|
||||
* @see java.lang.ref.Reference
|
||||
* @since Commons Collections 3.0 (previously in main package v2.1)
|
||||
*/
|
||||
public class ReferenceMap <K,V> extends AbstractReferenceMap<K, V> implements Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version
|
||||
*/
|
||||
private static final long serialVersionUID = 1555089888138299607L;
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ReferenceMap</code> that will
|
||||
* use hard references to keys and soft references to values.
|
||||
*/
|
||||
public ReferenceMap() {
|
||||
super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ReferenceMap</code> that will
|
||||
* use the specified types of references.
|
||||
*
|
||||
* @param keyType the type of reference to use for keys;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param valueType the type of reference to use for values;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
*/
|
||||
public ReferenceMap(int keyType, int valueType) {
|
||||
super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ReferenceMap</code> that will
|
||||
* use the specified types of references.
|
||||
*
|
||||
* @param keyType the type of reference to use for keys;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param valueType the type of reference to use for values;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param purgeValues should the value be automatically purged when the
|
||||
* key is garbage collected
|
||||
*/
|
||||
public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
|
||||
super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ReferenceMap</code> with the
|
||||
* specified reference types, load factor and initial
|
||||
* capacity.
|
||||
*
|
||||
* @param keyType the type of reference to use for keys;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param valueType the type of reference to use for values;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param capacity the initial capacity for the map
|
||||
* @param loadFactor the load factor for the map
|
||||
*/
|
||||
public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) {
|
||||
super(keyType, valueType, capacity, loadFactor, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new <code>ReferenceMap</code> with the
|
||||
* specified reference types, load factor and initial
|
||||
* capacity.
|
||||
*
|
||||
* @param keyType the type of reference to use for keys;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param valueType the type of reference to use for values;
|
||||
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
|
||||
* @param capacity the initial capacity for the map
|
||||
* @param loadFactor the load factor for the map
|
||||
* @param purgeValues should the value be automatically purged when the
|
||||
* key is garbage collected
|
||||
*/
|
||||
public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) {
|
||||
super(keyType, valueType, capacity, loadFactor, purgeValues);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Write the map out using a custom routine.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
doWriteObject(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the map in using a custom routine.
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
doReadObject(in);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// GenericsNote: Converted.
|
||||
/*
|
||||
* Copyright 2003-2004 The Apache Software Foundation
|
||||
*
|
||||
* 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 org.jivesoftware.smack.util.collections;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Defines an iterator that can be reset back to an initial state.
|
||||
* <p/>
|
||||
* This interface allows an iterator to be repeatedly reused.
|
||||
*
|
||||
* @author Matt Hall, John Watkinson, Stephen Colebourne
|
||||
* @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
|
||||
* @since Commons Collections 3.0
|
||||
*/
|
||||
public interface ResettableIterator <E> extends Iterator<E> {
|
||||
|
||||
/**
|
||||
* Resets the iterator back to the position at which the iterator
|
||||
* was created.
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue