KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > messenger > muc > HistoryStrategy


1 /**
2  * $RCSfile: HistoryStrategy.java,v $
3  * $Revision: 1.8 $
4  * $Date: 2005/04/11 21:04:01 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.messenger.muc;
13
14 import org.jivesoftware.util.JiveGlobals;
15 import org.jivesoftware.util.Log;
16 import org.xmpp.packet.Message;
17
18 import java.util.Iterator JavaDoc;
19 import java.util.LinkedList JavaDoc;
20 import java.util.ListIterator JavaDoc;
21
22 /**
23  * <p>Multi-User Chat rooms may cache history of the conversations in the room in order to
24  * play them back to newly arriving members.</p>
25  *
26  * <p>This class is an internal component of MUCRoomHistory that describes the strategy that can
27  * be used, and provides a method of administering the history behavior.</p>
28  *
29  * @author Gaston Dombiak
30  * @author Derek DeMoro
31  */

32 public class HistoryStrategy {
33
34     /**
35      * The type of strategy being used.
36      */

37     private Type type = Type.number;
38
39     /**
40      * List containing the history of messages.
41      */

42     private LinkedList JavaDoc history = new LinkedList JavaDoc();
43     /**
44      * Default max number.
45      */

46     private static final int DEFAULT_MAX_NUMBER = 25;
47     /**
48      * The maximum number of chat history messages stored for the room.
49      */

50     private int maxNumber;
51     /**
52      * The parent history used for default settings, or null if no parent
53      * (chat server defaults).
54      */

55     private HistoryStrategy parent;
56     /**
57      * Track the latest room subject change or null if none exists yet.
58      */

59     private Message roomSubject = null;
60     /**
61      * The string prefix to be used on the context property names
62      * (do not include trailing dot).
63      */

64     private String JavaDoc contextPrefix = null;
65
66     /**
67      * Create a history strategy with the given parent strategy (for defaults) or null if no
68      * parent exists.
69      *
70      * @param parentStrategy The parent strategy of this strategy or null if none exists.
71      */

72     public HistoryStrategy(HistoryStrategy parentStrategy) {
73         this.parent = parentStrategy;
74         if (parent == null) {
75             maxNumber = DEFAULT_MAX_NUMBER;
76         }
77         else {
78             type = Type.defaulType;
79             maxNumber = parent.getMaxNumber();
80         }
81     }
82
83     /**
84      * Obtain the maximum number of messages for strategies using message number limitations.
85      *
86      * @return The maximum number of messages to store in applicable strategies.
87      */

88     public int getMaxNumber() {
89         return maxNumber;
90     }
91
92     /**
93      * Set the maximum number of messages for strategies using message number limitations.
94      *
95      * @param max The maximum number of messages to store in applicable strategies.
96      */

97     public void setMaxNumber(int max) {
98         this.maxNumber = max;
99         if (contextPrefix != null){
100             JiveGlobals.setProperty(contextPrefix + ".maxNumber",
101                                     Integer.toString(maxNumber));
102         }
103     }
104
105     /**
106      * Set the type of history strategy being used.
107      *
108      * @param newType The new type of chat history to use.
109      */

110     public void setType(Type newType){
111         if (newType != null){
112             type = newType;
113         }
114         if (contextPrefix != null){
115             JiveGlobals.setProperty(contextPrefix + ".type", type.toString());
116         }
117     }
118
119     /**
120      * Obtain the type of history strategy being used.
121      *
122      * @return The current type of strategy being used.
123      */

124     public Type getType(){
125         return type;
126     }
127
128     /**
129      * Add a message to the current chat history. The strategy type will determine what
130      * actually happens to the message.
131      *
132      * @param packet The packet to add to the chatroom's history.
133      */

134     public void addMessage(Message packet){
135         // get the conditions based on default or not
136
Type strategyType;
137         int strategyMaxNumber;
138         if (type == Type.defaulType && parent != null) {
139             strategyType = parent.getType();
140             strategyMaxNumber = parent.getMaxNumber();
141         }
142         else {
143             strategyType = type;
144             strategyMaxNumber = maxNumber;
145         }
146
147         // Room subject change messages are special
148
boolean subjectChange = false;
149         if (packet.getSubject() != null && packet.getSubject().length() > 0){
150             subjectChange = true;
151             roomSubject = packet;
152         }
153
154         // store message according to active strategy
155
if (strategyType == Type.none){
156             if (subjectChange) {
157                 history.clear();
158                 history.add(packet);
159             }
160         }
161         else if (strategyType == Type.all) {
162             history.addLast(packet);
163         }
164         else if (strategyType == Type.number) {
165             if (history.size() >= strategyMaxNumber) {
166                 // We have to remove messages so the new message won't exceed
167
// the max history size
168
// This is complicated somewhat because we must skip over the
169
// last room subject
170
// message because we want to preserve the room subject if
171
// possible.
172
ListIterator JavaDoc historyIter = history.listIterator();
173                 while (historyIter.hasNext() && history.size() > strategyMaxNumber) {
174                     if (historyIter.next() != roomSubject) {
175                         historyIter.remove();
176                     }
177                 }
178             }
179             history.addLast(packet);
180         }
181     }
182
183     /**
184      * Obtain the current history as an iterator of messages to play back to a new room member.
185      *
186      * @return An iterator of Message objects to be sent to the new room member.
187      */

188     public Iterator JavaDoc getMessageHistory(){
189         LinkedList JavaDoc list = new LinkedList JavaDoc(history);
190         return list.iterator();
191     }
192
193     /**
194      * Obtain the current history to be iterated in reverse mode. This means that the returned list
195      * iterator will be positioned at the end of the history so senders of this message must
196      * traverse the list in reverse mode.
197      *
198      * @return A list iterator of Message objects positioned at the end of the list.
199      */

200     public ListIterator JavaDoc getReverseMessageHistory(){
201         LinkedList JavaDoc list = new LinkedList JavaDoc(history);
202         return list.listIterator(list.size());
203     }
204
205     /**
206      * Strategy type.
207      */

208     public enum Type {
209         defaulType, none, all, number;
210     }
211
212     /**
213      * Obtain the strategy type from string name. See the Type enumeration name
214      * strings for the names strings supported. If nothing matches
215      * and parent != null DEFAULT is used, otherwise, NUMBER is used.
216      *
217      * @param typeName The text name of the strategy type
218      */

219     public void setTypeFromString(String JavaDoc typeName) {
220         try {
221             setType(Type.valueOf(typeName));
222         }
223         catch (Exception JavaDoc e) {
224             if (parent != null) {
225                 setType(Type.defaulType);
226             }
227             else {
228                 setType(Type.number);
229             }
230         }
231     }
232
233     /**
234      * Sets the prefix to use for retrieving and saving settings (and also
235      * triggers an immediate loading of properties).
236      *
237      * @param prefix the prefix to use (without trailing dot) on property names.
238      */

239     public void setContext(String JavaDoc prefix) {
240         this.contextPrefix = prefix;
241         setTypeFromString(JiveGlobals.getProperty(prefix + ".type"));
242         String JavaDoc maxNumberString = JiveGlobals.getProperty(prefix + ".maxNumber");
243         if (maxNumberString != null && maxNumberString.trim().length() > 0){
244             try {
245                 setMaxNumber(Integer.parseInt(maxNumberString));
246             }catch (Exception JavaDoc e){
247                 Log.info("Jive property "
248                         + prefix + ".maxNumber not a valid number.");
249             }
250         }
251     }
252
253     /**
254      * Returns true if there is a message within the history of the room that has changed the
255      * room's subject.
256      *
257      * @return true if there is a message within the history of the room that has changed the
258      * room's subject.
259      */

260     public boolean hasChangedSubject() {
261         return roomSubject != null;
262     }
263 }
264
Popular Tags