001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack.chat; 019 020import java.util.Collections; 021import java.util.Set; 022import java.util.concurrent.CopyOnWriteArraySet; 023 024import org.jivesoftware.smack.SmackException.NotConnectedException; 025import org.jivesoftware.smack.StanzaCollector; 026import org.jivesoftware.smack.packet.Message; 027import org.jivesoftware.smack.util.StringUtils; 028 029import org.jxmpp.jid.EntityJid; 030 031/** 032 * A chat is a series of messages sent between two users. Each chat has a unique 033 * thread ID, which is used to track which messages are part of a particular 034 * conversation. Some messages are sent without a thread ID, and some clients 035 * don't send thread IDs at all. Therefore, if a message without a thread ID 036 * arrives it is routed to the most recently created Chat with the message 037 * sender. 038 * 039 * @author Matt Tucker 040 * @deprecated use <code>org.jivesoftware.smack.chat2.Chat</code> from <code>smack-extensions</code> instead. 041 */ 042@Deprecated 043public class Chat { 044 045 private final ChatManager chatManager; 046 private final String threadID; 047 private final EntityJid participant; 048 private final Set<ChatMessageListener> listeners = new CopyOnWriteArraySet<>(); 049 050 /** 051 * Creates a new chat with the specified user and thread ID. 052 * 053 * @param chatManager the chatManager the chat will use. 054 * @param participant the user to chat with. 055 * @param threadID the thread ID to use. 056 */ 057 Chat(ChatManager chatManager, EntityJid participant, String threadID) { 058 if (StringUtils.isEmpty(threadID)) { 059 throw new IllegalArgumentException("Thread ID must not be null"); 060 } 061 this.chatManager = chatManager; 062 this.participant = participant; 063 this.threadID = threadID; 064 } 065 066 /** 067 * Returns the thread id associated with this chat, which corresponds to the 068 * <tt>thread</tt> field of XMPP messages. This method may return <tt>null</tt> 069 * if there is no thread ID is associated with this Chat. 070 * 071 * @return the thread ID of this chat. 072 */ 073 public String getThreadID() { 074 return threadID; 075 } 076 077 /** 078 * Returns the name of the user the chat is with. 079 * 080 * @return the name of the user the chat is occuring with. 081 */ 082 public EntityJid getParticipant() { 083 return participant; 084 } 085 086 /** 087 * Sends the specified text as a message to the other chat participant. 088 * This is a convenience method for: 089 * 090 * <pre> 091 * Message message = chat.createMessage(); 092 * message.setBody(messageText); 093 * chat.sendMessage(message); 094 * </pre> 095 * 096 * @param text the text to send. 097 * @throws NotConnectedException 098 * @throws InterruptedException 099 */ 100 public void sendMessage(String text) throws NotConnectedException, InterruptedException { 101 Message message = new Message(); 102 message.setBody(text); 103 sendMessage(message); 104 } 105 106 /** 107 * Sends a message to the other chat participant. The thread ID, recipient, 108 * and message type of the message will automatically set to those of this chat. 109 * 110 * @param message the message to send. 111 * @throws NotConnectedException 112 * @throws InterruptedException 113 */ 114 public void sendMessage(Message message) throws NotConnectedException, InterruptedException { 115 // Force the recipient, message type, and thread ID since the user elected 116 // to send the message through this chat object. 117 message.setTo(participant); 118 message.setType(Message.Type.chat); 119 message.setThread(threadID); 120 chatManager.sendMessage(this, message); 121 } 122 123 /** 124 * Adds a stanza listener that will be notified of any new messages in the 125 * chat. 126 * 127 * @param listener a stanza listener. 128 */ 129 public void addMessageListener(ChatMessageListener listener) { 130 if (listener == null) { 131 return; 132 } 133 // TODO these references should be weak. 134 listeners.add(listener); 135 } 136 137 public void removeMessageListener(ChatMessageListener listener) { 138 listeners.remove(listener); 139 } 140 141 /** 142 * Closes the Chat and removes all references to it from the {@link ChatManager}. The chat will 143 * be unusable when this method returns, so it's recommend to drop all references to the 144 * instance right after calling {@link #close()}. 145 */ 146 public void close() { 147 chatManager.closeChat(this); 148 listeners.clear(); 149 } 150 151 /** 152 * Returns an unmodifiable set of all of the listeners registered with this chat. 153 * 154 * @return an unmodifiable set of all of the listeners registered with this chat. 155 */ 156 public Set<ChatMessageListener> getListeners() { 157 return Collections.unmodifiableSet(listeners); 158 } 159 160 /** 161 * Creates a {@link org.jivesoftware.smack.StanzaCollector} which will accumulate the Messages 162 * for this chat. Always cancel StanzaCollectors when finished with them as they will accumulate 163 * messages indefinitely. 164 * 165 * @return the StanzaCollector which returns Messages for this chat. 166 */ 167 public StanzaCollector createCollector() { 168 return chatManager.createStanzaCollector(this); 169 } 170 171 /** 172 * Delivers a message directly to this chat, which will add the message 173 * to the collector and deliver it to all listeners registered with the 174 * Chat. This is used by the XMPPConnection class to deliver messages 175 * without a thread ID. 176 * 177 * @param message the message. 178 */ 179 void deliver(Message message) { 180 // Because the collector and listeners are expecting a thread ID with 181 // a specific value, set the thread ID on the message even though it 182 // probably never had one. 183 message.setThread(threadID); 184 185 for (ChatMessageListener listener : listeners) { 186 listener.processMessage(this, message); 187 } 188 } 189 190 @Override 191 public String toString() { 192 return "Chat [(participant=" + participant + "), (thread=" + threadID + ")]"; 193 } 194 195 @Override 196 public int hashCode() { 197 int hash = 1; 198 hash = hash * 31 + threadID.hashCode(); 199 hash = hash * 31 + participant.hashCode(); 200 return hash; 201 } 202 203 @Override 204 public boolean equals(Object obj) { 205 return obj instanceof Chat 206 && threadID.equals(((Chat) obj).getThreadID()) 207 && participant.equals(((Chat) obj).getParticipant()); 208 } 209}