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}