diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java index b24388c4c..d78d271e6 100644 --- a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java +++ b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java @@ -33,7 +33,9 @@ public class MessageHistoryServiceImpl implements MessageHistoryService, MessageListener, - ServiceListener + ChatRoomMessageListener, + ServiceListener, + LocalUserChatRoomPresenceListener { /** * The logger for this class. @@ -213,7 +215,6 @@ public Collection findByPeriod(MetaContact contact, throws RuntimeException { return findByPeriod(contact, startDate, endDate, keywords, false); - } /** @@ -341,7 +342,6 @@ public Collection findFirstMessagesAfter(MetaContact contact, Date date, startIndex = 0; return resultAsList.subList(startIndex, resultAsList.size()); - } /** @@ -424,6 +424,71 @@ private History getHistory(Contact localContact, Contact remoteContact) return retVal; } + + /** + * Returns the history by specified local contact + * (if is null the default is used) + * and by the chat room + * + * @param room The chat room + * @return History the history - created if not existing + * @throws IOException + */ + private History getHistoryForMultiChat( + Contact localContact, + ChatRoom room) + throws IOException + { + AccountID account = room.getParentProvider().getAccountID(); + + return this.getHistoryForMultiChat( + null, + account.getAccountUniqueID(), + account.getService(), + room.getName()); + } + + /** + * Returns the history by specified local contact + * (if is null the default is used) + * and by accountUniqueID, channel and server + * used by the multichat account. + * + * @param localContact Contact + * @param account The account UniqueID + * @param server the server used by the account + * @param channel the channel history we are searching for + * @return History the history - created if not existing + * @throws IOException + */ + private History getHistoryForMultiChat( + Contact localContact, + String account, + String server, + String channel) + throws IOException + { + History retVal = null; + + String localId = localContact == null ? "default" : localContact + .getAddress(); + + HistoryID historyId = HistoryID.createFromID( + new String[] { "messages", + localId, + account, + channel + "@" + server }); + + if (this.historyService.isHistoryExisting(historyId)) + { + retVal = this.historyService.getHistory(historyId); + } else { + retVal = this.historyService.createHistory(historyId, + recordStructure); + } + + return retVal; + } /** * Used to convert HistoryRecord in MessageDeliveredEvent or MessageReceivedEvent @@ -466,6 +531,56 @@ private Object convertHistoryRecordToMessageEvent(HistoryRecord hr, Contact cont contact, timestamp); } + + /** + * Used to convert HistoryRecord in ChatRoomMessageDeliveredEvent or + * ChatRoomMessageReceivedEvent + * which are returned by the finder methods + * + * @param hr HistoryRecord + * @param contact Contact + * @return Object + */ + private Object convertHistoryRecordToMessageEvent( + HistoryRecord hr, ChatRoom room) + { + MessageImpl msg = new MessageImpl(hr); + Date timestamp = null; + + // if there is value for date of receiving the message + // this is the event timestamp (this is the date that had came from protocol) + // the HistoryRecord timestamp is the timestamp when the record was written + if(msg.getMessageReceivedDate() != null) + { + if(msg.getMessageReceivedDate().after(hr.getTimestamp()) && + (msg.getMessageReceivedDate().getTime() - + hr.getTimestamp().getTime()) > 86400000) // 24*60*60*1000 + timestamp = hr.getTimestamp(); + else + timestamp = msg.getMessageReceivedDate(); + } + else + timestamp = hr.getTimestamp(); + + // 5 is the index of the subject in the structure + String fromStr = hr.getPropertyValues()[5]; + + ChatRoomMember from = new ChatRoomMemberImpl(fromStr, room, null); + + if(msg.isOutgoing) + { + return new ChatRoomMessageDeliveredEvent( + room, + timestamp, + msg); + } + else + return new ChatRoomMessageReceivedEvent( + room, + from, + timestamp, + msg); + } /** * starts the service. Check the current registerd protocol providers @@ -571,13 +686,52 @@ public void messageDelivered(MessageDeliveredEvent evt) public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) { } + + // ////////////////////////////////////////////////////////////////////////// + // ChatRoomMessageListener implementation methods + + public void messageReceived(ChatRoomMessageReceivedEvent evt) + { + try + { + History history = this.getHistoryForMultiChat( + null, + evt.getSourceChatRoom()); + + writeMessage(history, "in", evt.getSourceChatRoomMember(), + evt.getMessage(), evt.getTimestamp()); + } catch (IOException e) + { + logger.error("Could not add message to history", e); + } + } + + public void messageDelivered(ChatRoomMessageDeliveredEvent evt) + { + try + { + History history = this. + getHistoryForMultiChat( + null, + evt.getSourceChatRoom()); + + writeMessage(history, "out", evt.getMessage(), evt.getTimestamp()); + } catch (IOException e) + { + logger.error("Could not add message to history", e); + } + } + public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt) + { + } + /** - * - * @param direction String - * @param source Contact - * @param destination Contact - * @param message Message + * Writes message to the history + * @param direction String direction of the message + * @param source The source Contact + * @param destination The destiantion Contact + * @param message Message message to be written * @param messageTimestamp Date this is the timestamp when was message received * that came from the protocol provider */ @@ -586,6 +740,25 @@ private void writeMessage(String direction, Contact source, { try { History history = this.getHistory(source, destination); + + writeMessage(history, direction, message, messageTimestamp); + } catch (IOException e) + { + logger.error("Could not add message to history", e); + } + } + + /** + * Writes message to the history + * @param history The history to which will write the message + * @param message Message + * @param messageTimestamp Date this is the timestamp when was message received + * that came from the protocol provider + */ + private void writeMessage(History history, String direction, + Message message, Date messageTimestamp) + { + try { HistoryWriter historyWriter = history.getWriter(); historyWriter.addRecord(new String[] { direction, message.getContent(), message.getContentType(), @@ -597,6 +770,32 @@ private void writeMessage(String direction, Contact source, logger.error("Could not add message to history", e); } } + + /** + * Writes message to the history + * @param history The history to which will write the message + * @param message Message + * @param messageTimestamp Date this is the timestamp when was message received + * that came from the protocol provider + */ + private void writeMessage(History history, String direction, + ChatRoomMember from, + Message message, Date messageTimestamp) + { + try { + HistoryWriter historyWriter = history.getWriter(); + historyWriter.addRecord(new String[] { direction, + message.getContent(), message.getContentType(), + message.getEncoding(), message.getMessageUID(), + from.getContactAddress(), + String.valueOf(messageTimestamp.getTime()) }, + new Date()); // this date is when the history record is written + } catch (IOException e) + { + logger.error("Could not add message to history", e); + } + } + // ////////////////////////////////////////////////////////////////////////// /** @@ -691,6 +890,29 @@ private void handleProviderAdded(ProtocolProviderService provider) { logger.trace("Service did not have a im op. set."); } + + OperationSetMultiUserChat opSetMultiUChat + = (OperationSetMultiUserChat) provider + .getSupportedOperationSets().get( + OperationSetMultiUserChat.class.getName()); + + if (opSetMultiUChat != null) + { + Iterator iter = + opSetMultiUChat.getCurrentlyJoinedChatRooms().iterator(); + + while(iter.hasNext()) + { + ChatRoom room = (ChatRoom)iter.next(); + room.addMessageListener(this); + } + + opSetMultiUChat.addPresenceListener(this); + } + else + { + logger.trace("Service did not have a multi im op. set."); + } } /** @@ -710,6 +932,43 @@ private void handleProviderRemoved(ProtocolProviderService provider) { opSetIm.removeMessageListener(this); } + + OperationSetMultiUserChat opSetMultiUChat + = (OperationSetMultiUserChat) provider + .getSupportedOperationSets().get( + OperationSetMultiUserChat.class.getName()); + + if (opSetMultiUChat != null) + { + Iterator iter = + opSetMultiUChat.getCurrentlyJoinedChatRooms().iterator(); + + while(iter.hasNext()) + { + ChatRoom room = (ChatRoom)iter.next(); + room.removeMessageListener(this); + } + } + } + + /** + * Called to notify interested parties that a change in our presence in + * a chat room has occured. Changes may include us being kicked, join, + * left. + * @param evt the LocalUserChatRoomPresenceChangeEvent instance + * containing the chat room and the type, and reason of the change + */ + public void localUserPresenceChanged(LocalUserChatRoomPresenceChangeEvent evt) + { + if(evt.getEventType() == + LocalUserChatRoomPresenceChangeEvent.CHAT_ROOM_JOINED) + { + evt.getChatRoom().addMessageListener(this); + } + else + { + evt.getChatRoom().removeMessageListener(this); + } } /** @@ -951,6 +1210,422 @@ private Hashtable getHistoryReaders(MetaContact contact) } return readers; } + + /** + * Returns all the messages exchanged in the supplied + * chat room after the given date + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByStartDate(ChatRoom room, Date startDate) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader.findByStartDate(startDate); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns all the messages exchanged + * in the supplied chat room before the given date + * + * @param room The chat room + * @param endDate Date the end date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByEndDate(ChatRoom room, Date endDate) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader.findByEndDate(endDate); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, Date startDate, Date endDate) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader.findByPeriod(startDate, endDate); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates and having the given + * keywords + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @param keywords array of keywords + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, + Date startDate, Date endDate, String[] keywords) + throws RuntimeException + { + return findByPeriod(room, startDate, endDate, keywords, false); + } + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates and having the given + * keywords + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @param keywords array of keywords + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, Date startDate, Date endDate, + String[] keywords, boolean caseSensitive) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader.findByPeriod(startDate, endDate, keywords, + SEARCH_FIELD, caseSensitive); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns all the messages exchanged + * in the supplied room having the given keyword + * + * @param room The Chat room + * @param keyword keyword + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeyword(ChatRoom room, String keyword) + throws RuntimeException + { + return findByKeyword(room, keyword, false); + } + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keyword + * + * @param room The chat room + * @param keyword keyword + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeyword(ChatRoom room, String keyword, + boolean caseSensitive) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader. + findByKeyword(keyword, SEARCH_FIELD, caseSensitive); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keywords + * + * @param room The chat room + * @param keywords keyword + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeywords(ChatRoom room, String[] keywords) + throws RuntimeException + { + return findByKeywords(room, keywords, false); + } + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keywords + * + * @param room The chat room + * @param keywords keyword + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeywords(ChatRoom room, String[] keywords, + boolean caseSensitive) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + + // add the progress listeners + addHistorySearchProgressListeners(reader, 1); + + Iterator recs = reader. + findByKeywords(keywords, SEARCH_FIELD, caseSensitive); + while (recs.hasNext()) + { + result.add(convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), room)); + } + + removeHistorySearchProgressListeners(reader); + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + return result; + } + + /** + * Returns the supplied number of recent messages exchanged + * in the supplied chat room + * + * @param room The chat room + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findLast(ChatRoom room, int count) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + + try + { + // get the readers for this room + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + Iterator recs = reader.findLast(count); + while (recs.hasNext()) + { + result.add( + convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), + room)); + + } + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + LinkedList resultAsList = new LinkedList(result); + int startIndex = resultAsList.size() - count; + + if(startIndex < 0) + startIndex = 0; + + return resultAsList.subList(startIndex, resultAsList.size()); + } + + /** + * Returns the supplied number of recent messages after the given date + * exchanged in the supplied chat room + * + * @param room The chat room + * @param date messages after date + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findFirstMessagesAfter(ChatRoom room, Date date, int count) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + + try + { + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + Iterator recs = reader.findFirstRecordsAfter(date, count); + while (recs.hasNext()) + { + result.add( + convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), + room)); + + } + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + LinkedList resultAsList = new LinkedList(result); + int startIndex = resultAsList.size() - count; + + if(startIndex < 0) + startIndex = 0; + + return resultAsList.subList(startIndex, resultAsList.size()); + } + + /** + * Returns the supplied number of recent messages before the given date + * exchanged in the supplied chat room + * + * @param room The chat room + * @param date messages before date + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findLastMessagesBefore(ChatRoom room, Date date, int count) + throws RuntimeException + { + TreeSet result = new TreeSet(new ChatRoomMessageEventComparator()); + + try + { + HistoryReader reader = + this.getHistoryForMultiChat(null, room).getReader(); + Iterator recs = reader.findLastRecordsBefore(date, count); + while (recs.hasNext()) + { + result.add( + convertHistoryRecordToMessageEvent( + (HistoryRecord)recs.next(), + room)); + + } + } catch (IOException e) + { + logger.error("Could not read history", e); + } + + LinkedList resultAsList = new LinkedList(result); + int startIndex = resultAsList.size() - count; + + if(startIndex < 0) + startIndex = 0; + + return resultAsList.subList(startIndex, resultAsList.size()); + } /** * A wrapper around HistorySearchProgressListener @@ -1145,4 +1820,79 @@ else if(o2 instanceof MessageReceivedEvent) return date1.compareTo(date2); } } -} + + /** + * Used to compare ChatRoomMessageDeliveredEvent + * or ChatRoomMessageReceivedEvent + * and to be ordered in TreeSet according their timestamp + */ + private class ChatRoomMessageEventComparator + implements Comparator + { + public int compare(Object o1, Object o2) + { + Date date1 = null; + Date date2 = null; + + if(o1 instanceof ChatRoomMessageDeliveredEvent) + date1 = ((ChatRoomMessageDeliveredEvent)o1).getTimestamp(); + else if(o1 instanceof ChatRoomMessageReceivedEvent) + date1 = ((ChatRoomMessageReceivedEvent)o1).getTimestamp(); + else + return 0; + + if(o2 instanceof ChatRoomMessageDeliveredEvent) + date2 = ((ChatRoomMessageDeliveredEvent)o2).getTimestamp(); + else if(o2 instanceof ChatRoomMessageReceivedEvent) + date2 = ((ChatRoomMessageReceivedEvent)o2).getTimestamp(); + else + return 0; + + return date1.compareTo(date2); + } + } + + /** + * Simple ChatRoomMember implementation. + */ + class ChatRoomMemberImpl + implements ChatRoomMember + { + private ChatRoom chatRoom; + private String name; + private ChatRoomMemberRole role; + + public ChatRoomMemberImpl(String name, ChatRoom chatRoom, + ChatRoomMemberRole role) + { + this.chatRoom = chatRoom; + this.name = name; + this.role = role; + } + + public ChatRoom getChatRoom() + { + return chatRoom; + } + + public ProtocolProviderService getProtocolProvider() + { + return chatRoom.getParentProvider(); + } + + public String getContactAddress() + { + return name; + } + + public String getName() + { + return name; + } + + public ChatRoomMemberRole getRole() + { + return role; + } + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockBasicInstantMessaging.java b/src/net/java/sip/communicator/impl/protocol/mock/MockBasicInstantMessaging.java index 192f4eb33..405d0453f 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockBasicInstantMessaging.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockBasicInstantMessaging.java @@ -77,7 +77,7 @@ public void addMessageListener(MessageListener listener) public Message createMessage(byte[] content, String contentType, String contentEncoding, String subject) { - return new MessageImpl(new String(content), contentType + return new MockMessage(new String(content), contentType , contentEncoding, subject); } @@ -90,7 +90,7 @@ public Message createMessage(byte[] content, String contentType, */ public Message createMessage(String messageText) { - return new MessageImpl(messageText, DEFAULT_MIME_TYPE, + return new MockMessage(messageText, DEFAULT_MIME_TYPE, DEFAULT_MIME_ENCODING, null); } @@ -187,69 +187,4 @@ public void deliverMessage(String to, Message msg) listener.messageReceived(msgReceivedEvt); } } - - public class MessageImpl - implements Message - { - private String textContent = null; - - private String contentType = null; - - private String contentEncoding = null; - - private String messageUID = null; - - private String subject = null; - - public MessageImpl(String content, - String contentType, - String contentEncoding, - String subject) - { - this.textContent = content; - this.contentType = contentType; - this.contentEncoding = contentEncoding; - this.subject = subject; - - //generate the uid - this.messageUID = String.valueOf( System.currentTimeMillis()) - + String.valueOf(hashCode()); - - } - - public String getContent() - { - return textContent; - } - - public String getContentType() - { - return contentType; - } - - public String getEncoding() - { - return contentEncoding; - } - - public String getMessageUID() - { - return messageUID; - } - - public byte[] getRawData() - { - return getContent().getBytes(); - } - - public int getSize() - { - return getContent().length(); - } - - public String getSubject() - { - return subject; - } - } -} +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java new file mode 100644 index 000000000..14ab0a0f6 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java @@ -0,0 +1,1205 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.mock; + +import java.util.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +/** + * + * @author Damian Minkov + */ +public class MockChatRoom + implements ChatRoom +{ + private MockProvider provider; + + private MockMultiUserChat parentOpSet = null; + + private String name; + + private String subject; + + private String nickname; + + private String roomPassword; + + private boolean joined = false; + + private int userLimit = Integer.MAX_VALUE; + + private List members = new Vector(); + + private Vector banMasks = new Vector(); + + /** + * Currently registered member presence listeners. + */ + private Vector memberPresenceListeners = new Vector(); + + /** + * Currently registered local user role listeners. + */ + private Vector localUserRoleListeners = new Vector(); + + /** + * Currently registered member role listeners. + */ + private Vector memberRoleListeners = new Vector(); + + /** + * Currently registered property change listeners. + */ + private Vector propertyChangeListeners = new Vector(); + + /** + * Currently registered message listeners. + */ + private Vector messageListeners = new Vector(); + + /** + * Currently registered join chatroom listeners. + */ + private Vector chatRoomJoinListeners = new Vector(); + + + public MockChatRoom( + MockProvider provider, + MockMultiUserChat parentOpSet, + String roomName) + { + this.provider = provider; + this.name = roomName; + this.parentOpSet = parentOpSet; + } + + /** + * Returns the name of this ChatRoom. + * + * @return a String containing the name of this ChatRoom. + */ + public String getName() + { + return name; + } + + /** + * Joins this chat room with the nickname of the local user so that the + * user would start receiving events and messages for it. + * + * @throws OperationFailedException with the corresponding code if an error + * occurs while joining the room. + */ + public void join() + throws OperationFailedException + { + joinAs(null, null); + } + + /** + * Joins this chat room so that the user would start receiving events and + * messages for it. The method uses the nickname of the local user and the + * specified password in order to enter the chatroom. + * + * @param password the password to use when authenticating on the chatroom. + * @throws OperationFailedException with the corresponding code if an error + * occurs while joining the room. + */ + public void join(byte[] password) + throws OperationFailedException + { + joinAs(null, password); + } + + /** + * Joins this chat room with the specified nickname so that the user would + * start receiving events and messages for it. If the chatroom already + * contains a user with this nickname, the method would throw an + * OperationFailedException with code IDENTIFICATION_CONFLICT. + * + * @param nickname the nickname to use. + * @throws OperationFailedException with the corresponding code if an error + * occurs while joining the room. + */ + public void joinAs(String nickname) + throws OperationFailedException + { + joinAs(nickname, null); + } + + /** + * Joins this chat room with the specified nickname and password so that the + * user would start receiving events and messages for it. If the chatroom + * already contains a user with this nickname, the method would throw an + * OperationFailedException with code IDENTIFICATION_CONFLICT. + * + * @param nickname the nickname to use. + * @param password a password necessary to authenticate when joining the + * room. + * @throws OperationFailedException with the corresponding code if an error + * occurs while joining the room. + */ + public void joinAs(String nickname, byte[] password) + throws OperationFailedException + { + if(nickname == null) + nickname = getParentProvider().getAccountID().getUserID(); + + this.nickname = nickname; + this.joined = true; + + MockChatRoomMember newMember = + new MockChatRoomMember(nickname, this, ChatRoomMemberRole.MEMBER); + + members.add(newMember); + + ChatRoomJoinedEvent event = + new ChatRoomJoinedEvent(this); + + Iterator iter = chatRoomJoinListeners.iterator(); + while(iter.hasNext()) + { + ChatRoomJoinListener elem = + (ChatRoomJoinListener)iter.next(); + + elem.chatRoomJoined(event); + } + + LocalUserChatRoomPresenceChangeEvent evt = + new LocalUserChatRoomPresenceChangeEvent( + parentOpSet, + this, + LocalUserChatRoomPresenceChangeEvent.CHAT_ROOM_JOINED, + null); + parentOpSet.fireLocalUserChatRoomPresenceChangeEvent(evt); + } + + /** + * Returns true if the local user is currently in the multi user chat + * (after calling one of the {@link #join()} methods). + * + * @return true if currently we're currently in this chat room and false + * otherwise. + */ + public boolean isJoined() + { + return joined; + } + + /** + * Leave this chat room. Once this method is called, the user won't be + * listed as a member of the chat room any more and no further chat events + * will be delivered. Depending on the underlying protocol and + * implementation leave() might cause the room to be destroyed if it has + * been created by the local user. + */ + public void leave() + { + + } + + /** + * Returns the last known room subject/theme or null if the user + * hasn't joined the room or the room does not have a subject yet. + *

+ * To be notified every time the room's subject change you should add a + * ChatRoomChangelistener to this room. + * {@link #addPropertyChangeListener(ChatRoomPropertyChangeListener)} + *

+ * To change the room's subject use {@link #setSubject(String)}. + * + * @return the room subject or null if the user hasn't joined the + * room or the room does not have a subject yet. + */ + public String getSubject() + { + return subject; + } + + /** + * Sets the subject of this chat room. If the user does not have the right + * to change the room subject, or the protocol does not support this, or + * the operation fails for some other reason, the method throws an + * OperationFailedException with the corresponding code. + * + * @param subject the new subject that we'd like this room to have + * @throws OperationFailedException + */ + public void setSubject(String subject) + throws OperationFailedException + { + this.subject = subject; + } + + /** + * Returns the local user's nickname in the context of this chat room or + * null if not currently joined. + * + * @return the nickname currently being used by the local user in the + * context of the local chat room. + */ + public String getUserNickname() + { + return nickname; + } + + /** + * Changes the the local user's nickname in the context of this chatroom. + * If the operation is not supported by the underlying implementation, the + * method throws an OperationFailedException with the corresponding code. + * + * @param nickname the new nickname within the room. + * + * @throws OperationFailedException if the setting the new nickname changes + * for some reason. + */ + public void setNickname(String nickname) + throws OperationFailedException + { + this.nickname = nickname; + } + + /** + * Adds a listener that will be notified of changes in our participation in + * the room such as us being kicked, join, left... + * + * @param listener a member participation listener. + */ + public void addMemberPresenceListener( + ChatRoomMemberPresenceListener listener) + { + if(!memberPresenceListeners.contains(listener)) + memberPresenceListeners.add(listener); + } + + /** + * Removes a listener that was being notified of changes in the + * participation of other chat room participants such as users being kicked, + * join, left. + * + * @param listener a member participation listener. + */ + public void removeMemberPresenceListener( + ChatRoomMemberPresenceListener listener) + { + memberPresenceListeners.remove(listener); + } + + /** + * Adds a listener that will be notified of changes in our role in the room + * such as us being granded operator. + * + * @param listener a local user role listener. + */ + public void addLocalUserRoleListener(ChatRoomLocalUserRoleListener listener) + { + if(!localUserRoleListeners.contains(listener)) + localUserRoleListeners.add(listener); + } + + /** + * Removes a listener that was being notified of changes in our role in this + * chat room such as us being granded operator. + * + * @param listener a local user role listener. + */ + public void removelocalUserRoleListener( + ChatRoomLocalUserRoleListener listener) + { + localUserRoleListeners.remove(listener); + } + + /** + * Adds a listener that will be notified of changes of a member role in the + * room such as being granded operator. + * + * @param listener a member role listener. + */ + public void addMemberRoleListener(ChatRoomMemberRoleListener listener) + { + if(!memberRoleListeners.contains(listener)) + memberRoleListeners.add(listener); + } + + /** + * Removes a listener that was being notified of changes of a member role in + * this chat room such as us being granded operator. + * + * @param listener a member role listener. + */ + public void removeMemberRoleListener(ChatRoomMemberRoleListener listener) + { + memberRoleListeners.remove(listener); + } + + /** + * Adds a listener that will be notified of changes in the property of the + * room such as the subject being change or the room state being changed. + * + * @param listener a property change listener. + */ + public void addPropertyChangeListener( + ChatRoomPropertyChangeListener listener) + { + if(!propertyChangeListeners.contains(listener)) + propertyChangeListeners.add(listener); + } + + /** + * Removes a listener that was being notified of changes in the property of + * the chat room such as the subject being change or the room state being + * changed. + * + * @param listener a property change listener. + */ + public void removePropertyChangeListener( + ChatRoomPropertyChangeListener listener) + { + propertyChangeListeners.remove(listener); + } + + /** + * Invites another user to this room. + *

+ * If the room is password-protected, the invitee will receive a password to + * use to join the room. If the room is members-only, the the invitee may + * be added to the member list. + * + * @param userAddress the address of the user to invite to the room.(one + * may also invite users not on their contact list). + * @param reason a reason, subject, or welcome message that would tell the + * the user why they are being invited. + */ + public void invite(String userAddress, String reason) + { + + } + + /** + * Returns a List of ChatRoomMembers corresponding to all + * members currently participating in this room. + * + * @return a List of ChatRoomMember instances + * corresponding to all room members. + */ + public List getMembers() + { + return members; + } + + /** + * Returns the number of participants that are currently in this chat room. + * @return int the number of Contacts, currently participating in + * this room. + */ + public int getMembersCount() + { + return members.size(); + } + + /** + * Registers listener so that it would receive events every time a + * new message is received on this chat room. + * @param listener a MessageListener that would be notified every + * time a new message is received on this chat room. + */ + public void addMessageListener(ChatRoomMessageListener listener) + { + if(!messageListeners.contains(listener)) + messageListeners.add(listener); + } + + /** + * Removes listener so that it won't receive any further message + * events from this room. + * @param listener the MessageListener to remove from this room + */ + public void removeMessageListener(ChatRoomMessageListener listener) + { + messageListeners.remove(listener); + } + + /** + * Create a Message instance for sending arbitrary MIME-encoding content. + * + * @param content content value + * @param contentType the MIME-type for content + * @param contentEncoding encoding used for content + * @param subject a String subject or null for now subject. + * @return the newly created message. + */ + public Message createMessage(byte[] content, String contentType, + String contentEncoding, String subject) + { + return new MockMessage(new String(content), contentType, + contentEncoding, subject); + } + + /** + * Create a Message instance for sending a simple text messages with default + * (text/plain) content type and encoding. + * + * @param messageText the string content of the message. + * @return Message the newly created message + */ + public Message createMessage(String messageText) + { + return new MockMessage(messageText); + } + + /** + * Sends the message to the destination indicated by the + * to contact. + * @param message the Message to send. + * @throws OperationFailedException if sending the message fails for some + * reason. + */ + public void sendMessage(Message message) + throws OperationFailedException + { + ChatRoomMessageDeliveredEvent evt = + new ChatRoomMessageDeliveredEvent( + this, + new Date(), + message); + + Iterator iter = messageListeners.iterator(); + while(iter.hasNext()) + { + ChatRoomMessageListener elem = + (ChatRoomMessageListener)iter.next(); + + elem.messageDelivered(evt); + } + } + + /** + * Returns a reference to the provider that created this room. + * + * @return a reference to the ProtocolProviderService instance + * that created this room. + */ + public ProtocolProviderService getParentProvider() + { + return provider; + } + + /** + * Sets the password of this chat room. If the user does not have the right + * to change the room password, or the protocol does not support this, or + * the operation fails for some other reason, the method throws an + * OperationFailedException with the corresponding code. + * + * @param password the new password that we'd like this room to have + * @throws OperationFailedException if the user does not have the right to + * change the room password, or the protocol does not support + * this, or the operation fails for some other reason + */ + public void setPassword(String password) + throws OperationFailedException + { + roomPassword = password; + } + + /** + * Returns the password of this chat room or null if the room doesn't have + * password. + * @return the password of this chat room or null if the room doesn't have + * password + */ + public String getPassword() + { + return roomPassword; + } + + /** + * Adds a ban mask to the list of ban masks of this chat room. The ban mask + * defines a group of users that will be banned. This property is meant to + * be used mainly by IRC implementations. If the user does not have the + * right to change the room ban list, or the protocol does not support this, + * or the operation fails for some other reason, the method throws an + * OperationFailedException with the corresponding code. + * + * @param banMask the new ban mask that we'd like to add to the room ban + * list + * @throws OperationFailedException if the user does not have the right to + * change the room ban list, or the protocol does not support this, or the + * operation fails for some other reason + */ + public void addBanMask(String banMask) + throws OperationFailedException + { + if(!banMasks.contains(banMask)) + banMasks.add(banMask); + } + + /** + * Remove a ban mask from the list of ban masks of this chat room. If the + * user does not have the right to change the room ban list, or the protocol + * does not support this, or the operation fails for some other reason, the + * method throws an OperationFailedException with the + * corresponding code. + * + * @param banMask the ban mask that we'd like to remove from this room ban + * list + * @throws OperationFailedException if the user does not have the right to + * change the room ban list, or the protocol does not support this, or the + * operation fails for some other reason + */ + public void removeBanMask(String banMask) + throws OperationFailedException + { + banMasks.remove(banMask); + } + + /** + * Sets the user limit of this chat room. The user limit is the maximum + * number of users, who could enter this chat room at a time. If the user + * does not have the right to change the room user limit, or the protocol + * does not support this, or the operation fails for some other reason, the + * method throws an OperationFailedException with the + * corresponding code. + * + * @param userLimit the new user limit that we'd like this room to have + * @throws OperationFailedException if the user does not have the right to + * change the room user limit, or the protocol does not support this, or the + * operation fails for some other reason + */ + public void setUserLimit(int userLimit) + throws OperationFailedException + { + this.userLimit = userLimit; + } + + /** + * Returns the limit of user for this chat room. The user limit is the + * maximum number of users, who could enter this chat room at a time. + * + * @return int the limit of user for this chat room + */ + public int getUserLimit() + { + return userLimit; + } + + /** + * Returns an Iterator over a set of ChatRoomConfigParams. Each + * element in the set is one of the ChatRoomConfigParams.CHAT_ROOM_XXX + * configuration params. This method is meant to be used by other bundles, + * before trying to change ChatRoom configurations, in order to + * check which are the supported configurations by the current + * implementation. + * + * @return an Iterator over a set of ChatRoomConfigParams + */ + public Iterator getSupportedConfigParams() + { + return new Vector().iterator(); + } + + /** + * Returns an Iterator over a set of ChatRoomConfigParams, + * containing the current configuration of this chat room. This method is + * meant to be used by bundles interested in what are the specific chat room + * configurations. + * + * @return an Iterator over a set of ChatRoomConfigParams, + * containing the current configuration of this chat room + */ + public Iterator getConfiguration() + { + return new Vector().iterator(); + } + + /** + * Returns an Iterator over a set of ban masks for this chat room. The ban + * mask defines a group of users that will be banned. The ban list is a list + * of all such ban masks defined for this chat room. + * + * @return an Iterator over a set of ban masks for this chat room + */ + public Iterator getBanList() + { + return new Vector().iterator(); + } + + /** + * Methods for manipulating mock operation set as + * deliver(receive) messageop + * + * @param msg the message that we are to deliver. + */ + public void deliverMessage(Message msg, String from) + { + ChatRoomMember fromMember = null; + Iterator iter = members.iterator(); + while(iter.hasNext()) + { + ChatRoomMember elem = (ChatRoomMember)iter.next(); + if(elem.getName().equals(from)) + { + fromMember = elem; + break; + } + } + + if(fromMember == null) + return; + + ChatRoomMessageReceivedEvent evt = + new ChatRoomMessageReceivedEvent( + this, + fromMember, + new Date(), + msg); + + iter = messageListeners.iterator(); + while(iter.hasNext()) + { + ChatRoomMessageListener elem = + (ChatRoomMessageListener)iter.next(); + + elem.messageReceived(evt); + } + } + + /** + * Changes the the local user's nickname in the context of this chatroom. + * If the operation is not supported by the underlying implementation, the + * method throws an OperationFailedException with the corresponding code. + * + * @param nickname the new nickname within the room. + * + * @throws OperationFailedException if the setting the new nickname changes + * for some reason. + */ + public void setUserNickname(String nickname) throws OperationFailedException + { + this.nickname = nickname; + } + + /** + * Indicates if this ChatRoom is visible to everyone and everyone + * could join it. If the ChatRoom is NOT visible, it cannot be seen + * without knowing the exact name. + * + * @return true if this ChatRoom is visible to + * everyone, otherwise - false. + */ + public boolean isVisible() + { + return true; + } + + /** + * Sets the property indicating if this ChatRoom is visible to + * everyone and everyone could join it. If the ChatRoom is NOT + * visible, it cannot be seen without knowing the exact name. + * + * @param isVisible indicates if this ChatRoom should be visible or + * not + */ + public void setVisible(boolean isVisible) + { + } + + /** + * Indicates if this ChatRoom requires a password to be joined. + * + * @return true if this ChatRoom requires a password + * to be joined, otherwise - false + */ + public boolean isPasswordRequired() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom requires a + * password to be joined. + * + * @param isPasswordRequired indicates if this ChatRoom requires a + * password to be joined. + */ + public void setPasswordRequired(boolean isPasswordRequired) + { + } + + /** + * Indicates if this ChatRoom requires an invitation. If the + * chat room requires invitation, the user could not join it without being + * invited. + * + * @return true if this ChatRoom requires invitation + * to joined, otherwise - false. + */ + public boolean isInvitationRequired() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom requires an + * invitation to be joined. If the chat room requires invitation, the user + * could not join it without being invited. + * + * @param isInvitationRequired indicates if this ChatRoom requires + * invitation to be joined + */ + public void setInvitationRequired(boolean isInvitationRequired) + { + } + + /** + * Indicates if this ChatRoom has a limit on number of users who + * could join it. + * + * @return true if the number of users who could join this + * ChatRoom is limited, otherwise - false + */ + public boolean isMemberNumberLimited() + { + return false; + } + + /** + * Sets the property inficating if this ChatRoom has a limit on + * number of users who could join it. + * + * @param isMemberNumberLimited indicates if this ChatRoom has a + * limit on number of users who could join it + */ + public void setMemberNumberLimited(boolean isMemberNumberLimited) + { + } + + /** + * Indicates if this ChatRoom is in a mute mode. If a + * ChatRoom is muted no messages could be obtained from it. + * + * @return true if this ChatRoom is in a mute mode, + * otherwise - false + */ + public boolean isMute() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom is in a mute mode. + * If a ChatRoom is muted no messages could be obtained from it. + * + * @param isMute indicates if this ChatRoom should be in a mute + * mode or not + */ + public void setMute(boolean isMute) + { + } + + /** + * Indicates if it's possible for someone to send messages to this + * ChatRoom even if they are not present inside the chat room. + * + * @return true if this ChatRoom allows external + * messages, otherwise - false + */ + public boolean isAllowExternalMessages() + { + return false; + } + + /** + * Sets the property indicating if it's possible for someone to send + * messages to this ChatRoom even if they are not present inside + * the chat room. + * + * @param isAllowExternalMessages indicates if this ChatRoom should + * allow external messages or not + */ + public void setAllowExternalMessages(boolean isAllowExternalMessages) + { + } + + /** + * Indicates if this ChatRoom is registered. + * + * @return true if this ChatRoom is registered, + * otherwise - false + */ + public boolean isRegistered() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom is registered or + * not. + * + * @param isRegistered indicates if this ChatRoom is registered + */ + public void setRegistered(boolean isRegistered) + { + } + + /** + * Indicates if the subject of this ChatRoom could be changed by + * non admin users. If the subject is locked only admin users could change + * it. + * + * @return true if only admin user could change the subject of + * this ChatRoom, otherwise - false + */ + public boolean isSubjectLocked() + { + return true; + } + + /** + * Sets the property indicating if the subject of this ChatRoom + * could be changed only by admin users. + * + * @param isSubjectLocked indicates if the subject of this ChatRoom + * is locked + */ + public void setSubjectLocked(boolean isSubjectLocked) + { + } + + /** + * Indicates if the message format in this ChatRoom could be + * modified. If the message formatting is allowed - we could have colored, + * underlined, etc. messages. + * + * @return true if message formatting in this ChatRoom + * is allowed, otherwise - false + */ + public boolean isAllowMessageFormatting() + { + return false; + } + + /** + * Sets the property indicating if the message format in this + * ChatRoom could be modified. If the message formatting is + * allowed - we could have colored, underlined, etc. messages. + * + * @param isAllowMessageFormatting indicates if the message formatting in + * this ChatRoom is allowed + */ + public void setAllowMessageFormatting(boolean isAllowMessageFormatting) + { + } + + /** + * Indicates is this ChatRoom room is currently in a message + * formatting filtered mode. The message formatting filtered mode means that + * all formatted messages (colored, underlined, etc.) are seen in standard + * format by other users. + * + * @return true if this ChatRoom is in message + * formatting filtered mode, otherwise - false + */ + public boolean isFilterMessageFormatting() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom room is currently + * in a message formatting filtered mode. The message formatting filtered + * mode means that all formatted messages (colored, underlined, etc.) are + * seen in standard format by other users. + * + * @param isFilterMessageFormatting indicates if this ChatRoom + * is currently is a message formatting filtered mode + */ + public void setFilterMessageFormatting(boolean isFilterMessageFormatting) + { + } + + /** + * Indicates if users can only join this ChatRoom in a specified + * interval of X seconds or the time of join is unlimited. + * + * @return true if this ChatRoom could be joined only + * in a specified interval of X seconds, otherwise - false + */ + public boolean isJoinTimeLimited() + { + return false; + } + + /** + * Sets the property indicating if users can only join this ChatRoom + * in a specified interval of X seconds or the time of join is unlimited. + * + * @param isJoinTimeLimited indicates if users can only join this + * ChatRoom in a specified interval of X seconds or the time of + * join is unlimited. + */ + public void setJoinTimeLimited(boolean isJoinTimeLimited) + { + } + + /** + * Indicates if sending invitation request is allowed in this + * ChatRoom. + * + * @return true if user is allowed to send invitation request + * from this ChatRoom, otherwise - false + */ + public boolean isAllowInvitationSend() + { + return false; + } + + /** + * Sets the property indicating if sending invitation request is allowed in + * this ChatRoom. + * + * @param isAllowInvitationSend indicates if sending invitation request is + * allowed in this ChatRoom + */ + public void setAllowInvitationSend(boolean isAllowInvitationSend) + { + } + + /** + * Indicates if receiving invitation request is allowed in this + * ChatRoom. + * + * @return true if user is allowed to receive invitation request + * in this ChatRoom, otherwise - false + */ + public boolean isAllowInvitationReceive() + { + return false; + } + + /** + * Sets the property indicating if receiving invitation request is allowed + * in this ChatRoom. + * + * @param isAllowInvitationReceive indicates if receiving invitation request + * is allowed in this ChatRoom + */ + public void setAllowInvitationReceive(boolean isAllowInvitationReceive) + { + } + + /** + * Indicates if users which join this ChatRoom are redirected to + * another one. + * + * @return true if users are redirected, otherwise - + * false + */ + public boolean isUserRedirected() + { + return false; + } + + /** + * Sets the property indicating if users in this ChatRoom are + * redirected to another one. + * + * @param isRedirected indicates if users in this ChatRoom are + * redirected to another one. + */ + public void setUserRedirected(boolean isRedirected) + { + } + + /** + * Indicates if users in this ChatRoom can or cannot change their + * nickname. + * + * @return true if users in this ChatRoom can NOT + * change their nickname, otherwise - false + */ + public boolean isUserNicknameLocked() + { + return false; + } + + /** + * Sets the property indicating if users in this ChatRoom can or + * cannot change their nickname. + * + * @param isUserNicknameLocked indicates if nicknames in this + * ChatRoom are locked and could not be changed by users or users + * are free to modify their nick as they want + */ + public void setUserNicknameLocked(boolean isUserNicknameLocked) + { + } + + /** + * Indicates if kicks are allowed in this ChatRoom. A kick tells the + * server to force a user to leave the chat room. Kick is a term inspired of + * the IRC protocol. + * + * @return true if kicks are allowed in this ChatRoom, + * otherwise - false + */ + public boolean isAllowKick() + { + return false; + } + + /** + * Sets the property indicating if kicks are allowed in this + * ChatRoom. A kick tells the server to force a user to leave the + * chat room. Kick is a term inspired of the IRC protocol. + * + * @param isAllowKick indicates if kicks are allowed in this + * ChatRoom + */ + public void setAllowKick(boolean isAllowKick) + { + } + + /** + * Indicates if only registered users can join this ChatRoom or + * it's opened for everyone. + * + * @return true if only registered users could join this + * ChatRoom, otherwise - false + */ + public boolean isRegisteredUserOnly() + { + return false; + } + + /** + * Sets the property indicating if only registered users can join this + * ChatRoom or it's opened for everyone. + * + * @param isRegisteredUserOnly indicates if only registered users can join + * this ChatRoom or it's opened for everyone. + */ + public void setRegisteredUserOnly(boolean isRegisteredUserOnly) + { + } + + /** + * Indicates if this ChatRoom allows special messages. + * + * @return true if special messages are allowed in this + * ChatRoom, otherwise - false + */ + public boolean isAllowSpecialMessage() + { + return false; + } + + /** + * Sets the property indicating if this ChatRoom allows special + * messages. + * + * @param isAllowSpecialMessage indicates this ChatRoom should + * allow special messages + */ + public void setAllowSpecialMessage(boolean isAllowSpecialMessage) + { + } + + /** + * Indicates if the list of nicknames in this chat room is currently + * visible. + * + * @return true if the list of nicknames in this + * ChatRoom is visible, otherwise - false + */ + public boolean isNicknameListVisible() + { + return false; + } + + /** + * Sets the property indicating if the list of nicknames in this chat room + * is currently visible. + * + * @param isNicknameListVisible indicates if the list of nicknames in this + * chat room should be visible. + */ + public void setNicknameListVisible(boolean isNicknameListVisible) + { + } + + /** + * Adds a configuration property to the configuration list of this chat + * room. If the user does not have the right to change the room + * configuration, or the protocol does not support this, or the operation + * fails for some other reason, the method throws an + * OperationFailedException with the corresponding code. + * + * @param propertyName the name of the configuration property to set + * @param propertyValue the value to set to the given configuration property + * @throws OperationFailedException if the user does not have the right to + * change the room configuration, or the protocol does not support this, or + * the operation fails for some other reason + */ + public void addAdvancedConfigProperty(String propertyName, String propertyValue) throws OperationFailedException + { + } + + /** + * Removes a configuration property from this chat room configuration list. + * If the user does not have the right to change the room state, or the + * protocol does not support this, or the operation fails for some other + * reason, the method throws an OperationFailedException with the + * corresponding code. + * + * @param propertyName the name of the configuration property to be removed + * + * @throws OperationFailedException if the user does not have the right to + * change the room configuration, or the protocol does not support this, or + * the operation fails for some other reason + */ + public void removeAdvancedConfigProperty(String propertyName) throws OperationFailedException + { + } + + /** + * Returns an Iterator over a set of ChatRoomConfigParams, + * containing the current configuration of this chat room. This method is + * meant to be used by bundles interested in what are the specific chat room + * configurations. + * + * @return a Map of (Property_Name, Property_Value) pairs, containing the + * current configuration of this chat room + */ + public Map getAdvancedConfigurationSet() + { + return new HashMap(); + } + + /** + * Adds a listener to join notifications. The listener will be fired + * anytime a ChatRoom has been joined. + * + * @param listener a join listener. + */ + public void addJoinListener(ChatRoomJoinListener listener) + { + if(!chatRoomJoinListeners.contains(listener)) + chatRoomJoinListeners.add(listener); + } + + /** + * Removes the given listener from the list of join listeners registered to + * receive events every time when a ChatRoom has been joined. + * + * @param listener the join listener to remove + */ + public void removeJoinListener(ChatRoomJoinListener listener) + { + chatRoomJoinListeners.remove(listener); + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java new file mode 100644 index 000000000..1d2f91b42 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java @@ -0,0 +1,90 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.mock; + +import net.java.sip.communicator.service.protocol.*; + +/** + * + * @author Damian Minkov + */ +public class MockChatRoomMember + implements ChatRoomMember +{ + private ChatRoom chatRoom; + private String name; + private ChatRoomMemberRole role; + + public MockChatRoomMember(String name, ChatRoom chatRoom, + ChatRoomMemberRole role) + { + this.chatRoom = chatRoom; + this.name = name; + this.role = role; + } + + /** + * Returns the chat room that this member is participating in. + * + * @return the ChatRoom instance that this member belongs to. + */ + public ChatRoom getChatRoom() + { + return chatRoom; + } + + /** + * Returns the protocol provider instance that this member has originated + * in. + * + * @return the ProtocolProviderService instance that created this + * member and its containing cht room + */ + public ProtocolProviderService getProtocolProvider() + { + return chatRoom.getParentProvider(); + } + + /** + * Returns the contact identifier representing this contact. In protocols + * like IRC this method would return the same as getName() but in others + * like Jabber, this method would return a full contact id uri. + * + * @return a String (contact address), uniquely representing the contact + * over the service the service being used by the associated protocol + * provider instance/ + */ + public String getContactAddress() + { + return name; + } + + /** + * Returns the name of this member as it is known in its containing + * chatroom (aka a nickname). The name returned by this method, may + * sometimes match the string returned by getContactID() which is actually + * the address of a contact in the realm of the corresponding protocol. + * + * @return the name of this member as it is known in the containing chat + * room (aka a nickname). + */ + public String getName() + { + return name; + } + + /** + * Returns the role of this chat room member in its containing room. + * + * @return a ChatRoomMemberRole instance indicating the role + * the this member in its containing chat room. + */ + public ChatRoomMemberRole getRole() + { + return role; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockMessage.java b/src/net/java/sip/communicator/impl/protocol/mock/MockMessage.java new file mode 100644 index 000000000..cf62c73e1 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockMessage.java @@ -0,0 +1,127 @@ +/* + * MockMessage.java + * + * Created on Jun 21, 2007, 3:10:21 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package net.java.sip.communicator.impl.protocol.mock; + +import net.java.sip.communicator.service.protocol.*; + +/** + * Message Impl. + * @author Damian Minkov + */ +public class MockMessage + implements Message +{ + private String textContent = null; + + private String contentType = null; + + private String contentEncoding = null; + + private String messageUID = null; + + private String subject = null; + + MockMessage(String content, + String contentType, + String contentEncoding, + String subject) + { + this.textContent = content; + this.contentType = contentType; + this.contentEncoding = contentEncoding; + this.subject = subject; + + //generate the uid + this.messageUID = String.valueOf( System.currentTimeMillis()) + + String.valueOf(hashCode()); + } + + MockMessage(String content) + { + this.textContent = content; + this.contentType = + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE; + this.contentEncoding = + OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING; + this.subject = null; + + //generate the uid + this.messageUID = String.valueOf( System.currentTimeMillis()) + + String.valueOf(hashCode()); + } + + /** + * Returns the content of this message if representable in text form or null + * if this message does not contain text data. + * @return a String containing the content of this message or null if the + * message does not contain data representable in text form. + */ + public String getContent() + { + return textContent; + } + + /** + * Returns the MIME type for the message content. + * @return a String containing the mime type of the message contant. + */ + public String getContentType() + { + return contentType; + } + + /** + * Returns the MIME content encoding of this message. + * @return a String indicating the MIME encoding of this message. + */ + public String getEncoding() + { + return contentEncoding; + } + + /** + * Returns a unique identifier of this message. + * @return a String that uniquely represents this message in the scope of + * this protocol. + */ + public String getMessageUID() + { + return messageUID; + } + + /** + * Get the raw/binary content of an instant message. + * @return a byte[] array containing message bytes. + */ + public byte[] getRawData() + { + return getContent().getBytes(); + } + + /** + * Returns the size of the content stored in this message. + * @return an int indicating the number of bytes that this message contains. + */ + public int getSize() + { + return getContent().length(); + } + + /** + * Returns the subject of this message or null if the message contains no + * subject. + * @return the subject of this message or null if the message contains no + * subject. + */ + public String getSubject() + { + return subject; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockMultiUserChat.java b/src/net/java/sip/communicator/impl/protocol/mock/MockMultiUserChat.java new file mode 100644 index 000000000..ea063bac4 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockMultiUserChat.java @@ -0,0 +1,310 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.protocol.mock; + +import java.util.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +/** + * Multiuser chat functionalites for the mock protocol. + * @author Damian Minkov + */ +public class MockMultiUserChat + implements OperationSetMultiUserChat, + ChatRoomJoinListener +{ + /** + * The protocol provider that created us. + */ + private MockProvider provider = null; + + private List existingChatRooms = new Vector(); + private List joinedChatRooms = new Vector(); + + /** + * Currently registered invitation listeners. + */ + private Vector invitationListeners = new Vector(); + + /** + * Currently registered invitation reject listeners. + */ + private Vector invitationRejectListeners = new Vector(); + + /** + * Currently registered local user chat room presence listeners. + */ + private Vector localUserChatRoomPresenceListeners = new Vector(); + + /** + * Creates an instance of this operation set keeping a reference to the + * parent protocol provider and presence operation set. + * + * @param provider The provider instance that creates us. + */ + public MockMultiUserChat(MockProvider provider) + { + this.provider = provider; + } + + /** + * Returns the List of Strings indicating chat rooms + * currently available on the server that this protocol provider is + * connected to. + * + * @return a java.util.List of the name Strings for chat + * rooms that are currently available on the server that this protocol + * provider is connected to. + * + * @throws OperationFailedException if we faile retrieving this list from + * the server. + * @throws OperationNotSupportedException if the server does not support + * multi user chat + */ + public List getExistingChatRooms() + throws OperationFailedException, + OperationNotSupportedException + { + return existingChatRooms; + } + + /** + * Returns a list of the chat rooms that we have joined and are currently + * active in. + * + * @return a List of the rooms where the user has joined using a + * given connection. + */ + public List getCurrentlyJoinedChatRooms() + { + return joinedChatRooms; + } + + /** + * Returns a list of the chat rooms that chatRoomMember has joined + * and is currently active in. + * + * @param chatRoomMember the chatRoomMember whose current ChatRooms we will + * be querying. + * @return a list of the chat rooms that chatRoomMember has + * joined and is currently active in. + * + * @throws OperationFailedException if an error occurs while trying to + * discover the room on the server. + * @throws OperationNotSupportedException if the server does not support + * multi user chat + */ + public List getCurrentlyJoinedChatRooms(ChatRoomMember chatRoomMember) + throws OperationFailedException, + OperationNotSupportedException + { + List result = new Vector(); + + Iterator iter = joinedChatRooms.iterator(); + + while(iter.hasNext()) + { + ChatRoom elem = (ChatRoom)iter.next(); + if(elem.getMembers().contains(chatRoomMember)) + result.add(elem); + } + + return result; + } + + /** + * Creates a room with the named roomName and according to the + * specified roomProperties on the server that this protocol + * provider is currently connected to. When the method returns the room the + * local user will not have joined it and thus will not receive messages on + * it until the ChatRoom.join() method is called. + *

+ * @param roomName the name of the ChatRoom to create. + * @param roomProperties properties specifying how the room should be + * created. + * @throws OperationFailedException if the room couldn't be created for some + * reason (e.g. room already exists; user already joined to an existant + * room or user has no permissions to create a chat room). + * @throws OperationNotSupportedException if chat room creation is not + * supported by this server + * + * @return the newly created ChatRoom named roomName. + */ + public ChatRoom createChatRoom(String roomName, Hashtable roomProperties) + throws OperationFailedException, + OperationNotSupportedException + { + MockChatRoom room = new MockChatRoom(provider, this, roomName); + existingChatRooms.add(room); + room.addJoinListener(this); + return room; + } + + /** + * Returns a reference to a chatRoom named roomName or null if no + * such room exists. + *

+ * @param roomName the name of the ChatRoom that we're looking for. + * @return the ChatRoom named roomName or null if no such + * room exists on the server that this provider is currently connected to. + * + * @throws OperationFailedException if an error occurs while trying to + * discover the room on the server. + * @throws OperationNotSupportedException if the server does not support + * multi user chat + */ + public ChatRoom findRoom(String roomName) + throws OperationFailedException, + OperationNotSupportedException + { + Iterator iter = existingChatRooms.iterator(); + while(iter.hasNext()) + { + ChatRoom elem = (ChatRoom)iter.next(); + if(elem.getName().equals(roomName)) + return elem; + } + + return null; + } + + /** + * Informs the sender of an invitation that we decline their invitation. + * + * @param invitation the invitation we are rejecting. + */ + public void rejectInvitation(ChatRoomInvitation invitation) + { + ChatRoomInvitationRejectedEvent evt = + new ChatRoomInvitationRejectedEvent( + invitation, + null, + null, + invitation.getReason(), + new Date()); + + Iterator iter = invitationRejectListeners.iterator(); + while(iter.hasNext()) + { + ChatRoomInvitationRejectionListener elem = + (ChatRoomInvitationRejectionListener)iter.next(); + elem.invitationRejected(evt); + } + } + + /** + * Adds a listener to invitation notifications. The listener will be fired + * anytime an invitation is received. + * + * @param listener an invitation listener. + */ + public void addInvitationListener(ChatRoomInvitationListener listener) + { + if(!invitationListeners.contains(listener)) + invitationListeners.add(listener); + } + + /** + * Removes listener from the list of invitation listeners + * registered to receive invitation events. + * + * @param listener the invitation listener to remove. + */ + public void removeInvitationListener(ChatRoomInvitationListener listener) + { + invitationListeners.remove(listener); + } + + /** + * Adds a listener to invitation notifications. The listener will be fired + * anytime an invitation is received. + * + * @param listener an invitation listener. + */ + public void addInvitationRejectionListener( + ChatRoomInvitationRejectionListener listener) + { + if(!invitationRejectListeners.contains(listener)) + invitationRejectListeners.add(listener); + } + + /** + * Removes the given listener from the list of invitation listeners + * registered to receive events every time an invitation has been rejected. + * + * @param listener the invitation listener to remove. + */ + public void removeInvitationRejectionListener( + ChatRoomInvitationRejectionListener listener) + { + invitationRejectListeners.remove(listener); + } + + /** + * Returns true if contact supports multi user chat sessions. + * + * @param contact reference to the contact whose support for chat rooms + * we are currently querying. + * @return a boolean indicating whether contact supports chatrooms. + */ + public boolean isMultiChatSupportedByContact(Contact contact) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Indicates that a new + * {@link net.java.sip.communicator.service.protocol.ChatRoom} has been + * joined. + * + * @param event the ChatRoomJoinedEvent containing the + * ChatRoom that has been joined + */ + public void chatRoomJoined(ChatRoomJoinedEvent event) + { + joinedChatRooms.add(event.getSourceChatRoom()); + existingChatRooms.add(event.getSourceChatRoom()); + } + + /** + * Adds a listener that will be notified of changes in our participation in + * a chat room such as us being kicked, joined, left. + * + * @param listener a local user participation listener. + */ + public void addPresenceListener( + LocalUserChatRoomPresenceListener listener) + { + if(!localUserChatRoomPresenceListeners.contains(listener)) + localUserChatRoomPresenceListeners.add(listener); + } + + /** + * Removes a listener that was being notified of changes in our + * participation in a room such as us being kicked, joined, left. + * + * @param listener a local user participation listener. + */ + public void removePresenceListener( + LocalUserChatRoomPresenceListener listener) + { + localUserChatRoomPresenceListeners.remove(listener); + } + + void fireLocalUserChatRoomPresenceChangeEvent( + LocalUserChatRoomPresenceChangeEvent evt) + { + Iterator iter = localUserChatRoomPresenceListeners.iterator(); + while(iter.hasNext()) + { + LocalUserChatRoomPresenceListener elem = + (LocalUserChatRoomPresenceListener)iter.next(); + elem.localUserPresenceChanged(evt); + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java b/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java index 648987121..4e43444d1 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java @@ -66,6 +66,10 @@ public MockProvider(String userName) this.supportedOperationSets.put( OperationSetBasicInstantMessaging.class.getName(), mockBImOpSet); + + this.supportedOperationSets.put( + OperationSetMultiUserChat.class.getName(), + new MockMultiUserChat(this)); MockOperationSetBasicTelephony mockTelphonyOpSet = new MockOperationSetBasicTelephony(this); diff --git a/src/net/java/sip/communicator/service/msghistory/MessageHistoryService.java b/src/net/java/sip/communicator/service/msghistory/MessageHistoryService.java index f82237a91..04811b04d 100644 --- a/src/net/java/sip/communicator/service/msghistory/MessageHistoryService.java +++ b/src/net/java/sip/communicator/service/msghistory/MessageHistoryService.java @@ -8,6 +8,7 @@ import java.util.*; +import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.contactlist.*; import net.java.sip.communicator.service.msghistory.event.*; @@ -189,4 +190,164 @@ public Collection findLastMessagesBefore(MetaContact contact, Date date, int cou * @param listener HistorySearchProgressListener */ public void removeSearchProgressListener(MessageHistorySearchProgressListener listener); + + /** + * Returns all the messages exchanged in the supplied + * chat room after the given date + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByStartDate(ChatRoom room, Date startDate) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room before the given date + * + * @param room The chat room + * @param endDate Date the end date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByEndDate(ChatRoom room, Date endDate) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, Date startDate, Date endDate) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates and having the given + * keywords + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @param keywords array of keywords + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, + Date startDate, Date endDate, String[] keywords) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room between the given dates and having the given + * keywords + * + * @param room The chat room + * @param startDate Date the start date of the conversations + * @param endDate Date the end date of the conversations + * @param keywords array of keywords + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByPeriod(ChatRoom room, Date startDate, Date endDate, + String[] keywords, boolean caseSensitive) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied room having the given keyword + * + * @param room The Chat room + * @param keyword keyword + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeyword(ChatRoom room, String keyword) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keyword + * + * @param room The chat room + * @param keyword keyword + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + Collection findByKeyword(ChatRoom room, String keyword, + boolean caseSensitive) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keywords + * + * @param room The chat room + * @param keywords keyword + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeywords(ChatRoom room, String[] keywords) + throws RuntimeException; + + /** + * Returns all the messages exchanged + * in the supplied chat room having the given keywords + * + * @param room The chat room + * @param keywords keyword + * @param caseSensitive is keywords search case sensitive + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findByKeywords(ChatRoom room, String[] keywords, + boolean caseSensitive) + throws RuntimeException; + + /** + * Returns the supplied number of recent messages exchanged + * in the supplied chat room + * + * @param room The chat room + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findLast(ChatRoom room, int count) + throws RuntimeException; + + /** + * Returns the supplied number of recent messages after the given date + * exchanged in the supplied chat room + * + * @param room The chat room + * @param date messages after date + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findFirstMessagesAfter(ChatRoom room, Date date, int count) + throws RuntimeException; + + /** + * Returns the supplied number of recent messages before the given date + * exchanged in the supplied chat room + * + * @param room The chat room + * @param date messages before date + * @param count messages count + * @return Collection of MessageReceivedEvents or MessageDeliveredEvents + * @throws RuntimeException + */ + public Collection findLastMessagesBefore(ChatRoom room, Date date, int count) + throws RuntimeException; } diff --git a/src/net/java/sip/communicator/service/protocol/event/LocalUserChatRoomPresenceListener.java b/src/net/java/sip/communicator/service/protocol/event/LocalUserChatRoomPresenceListener.java index 939d7ec36..1b37512fe 100644 --- a/src/net/java/sip/communicator/service/protocol/event/LocalUserChatRoomPresenceListener.java +++ b/src/net/java/sip/communicator/service/protocol/event/LocalUserChatRoomPresenceListener.java @@ -21,8 +21,9 @@ public interface LocalUserChatRoomPresenceListener * Called to notify interested parties that a change in our presence in * a chat room has occured. Changes may include us being kicked, join, * left. - * @param evt the LocalUserChatRoomPresenceListener instance + * @param evt the LocalUserChatRoomPresenceChangeEvent instance * containing the chat room and the type, and reason of the change */ - public void localUserPresenceChanged(LocalUserChatRoomPresenceListener evt); + public void localUserPresenceChanged( + LocalUserChatRoomPresenceChangeEvent evt); } diff --git a/test/net/java/sip/communicator/slick/msghistory/TestMsgHistoryService.java b/test/net/java/sip/communicator/slick/msghistory/TestMsgHistoryService.java index d15ff45ab..06f30f2fc 100644 --- a/test/net/java/sip/communicator/slick/msghistory/TestMsgHistoryService.java +++ b/test/net/java/sip/communicator/slick/msghistory/TestMsgHistoryService.java @@ -34,6 +34,8 @@ public class TestMsgHistoryService private static final Logger logger = Logger.getLogger(TestMsgHistoryService.class); static final String TEST_CONTACT_NAME = "Mincho_Penchev"; + + static final String TEST_ROOM_NAME = "test_room"; /** * The provider that we use to make a dummy server-stored contactlist @@ -46,6 +48,7 @@ public class TestMsgHistoryService */ public static MockPersistentPresenceOperationSet mockPresOpSet = null; public static MockBasicInstantMessaging mockBImOpSet = null; + public static MockMultiUserChat mockMultiChat = null; private static ServiceReference msgHistoryServiceRef = null; public static MessageHistoryService msgHistoryService = null; @@ -81,6 +84,10 @@ public static Test suite() new TestMsgHistoryService("writeRecords")); suite.addTest( new TestMsgHistoryService("readRecords")); + suite.addTest( + new TestMsgHistoryService("writeRecordsToMultiChat")); + suite.addTest( + new TestMsgHistoryService("readRecordsFromMultiChat")); suite.addTest( new TestMsgHistoryService("testPurgeLocalContactListCopy")); @@ -114,6 +121,10 @@ public void setupContact() mockBImOpSet = (MockBasicInstantMessaging) supportedOperationSets.get( OperationSetBasicInstantMessaging.class.getName()); + + mockMultiChat = + (MockMultiUserChat) supportedOperationSets.get( + OperationSetMultiUserChat.class.getName()); msgHistoryServiceRef = MsgHistoryServiceLick.bc. @@ -367,6 +378,231 @@ public void readRecords() assertTrue("Message no found", msgs.contains(messagesToSend[2].getContent())); } + + public void writeRecordsToMultiChat() + { + try + { + ChatRoom room = mockMultiChat.createChatRoom("test_room", null); + room.join(); + +// ChatRoom room = mockMultiChat.findRoom(TEST_ROOM_NAME); +// room.joinAs(TEST_CONTACT_NAME); + + // First deliver message, so they are stored by the message history service + room.sendMessage(messagesToSend[0]); + + this.controlDate1 = new Date(); + + Object lock = new Object(); + synchronized (lock) + { + // wait a moment + try + { + lock.wait(200); + } + catch (InterruptedException ex) + { + } + } + + room.sendMessage(messagesToSend[1]); + + room.sendMessage(messagesToSend[2]); + + this.controlDate2 = new Date(); + synchronized (lock) + { + // wait a moment + try + { + lock.wait(200); + } + catch (InterruptedException ex) + { + } + } + + room.sendMessage(messagesToSend[3]); + + room.sendMessage(messagesToSend[4]); + } + catch(OperationFailedException ex) + { + fail("Failed to create room : " + ex.getMessage()); + logger.error("Failed to create room", ex); + } + catch(OperationNotSupportedException ex) + { + fail("Failed to create room : " + ex.getMessage()); + logger.error("Failed to create room", ex); + } + } + + /** + * tests all read methods (finders) + */ + public void readRecordsFromMultiChat() + { + ChatRoom room = null; + + try + { + room = mockMultiChat.findRoom(TEST_ROOM_NAME); + + }catch(Exception ex) + { + fail("Cannot find room!" + ex.getMessage()); + } + + /** + * This matches all written messages, they are minimum 5 + */ + Collection rs = msgHistoryService.findByKeyword(room, "test"); + + assertTrue("Nothing found findByKeyword ", !rs.isEmpty()); + + Vector msgs = getChatMessages(rs); + + assertTrue("Messages too few - findByKeyword", msgs.size() >= 5); + + /** + * Will test case sernsitive and insensitive search + */ + rs = msgHistoryService.findByKeyword(room, "Test", false); + + assertTrue("Nothing found findByKeyword caseINsensitive search", !rs.isEmpty()); + + msgs = getChatMessages(rs); + + assertTrue("Messages too few - findByKeyword", msgs.size() >= 5); + + rs = msgHistoryService.findByKeyword(room, "Test", true); + + assertFalse("Something found by findByKeyword casesensitive search", !rs.isEmpty()); + + /** + * This must match also many messages, as tests are run many times + * but the minimum is 3 + */ + rs = msgHistoryService.findByEndDate(room, controlDate2); + + assertTrue("Nothing found findByEndDate", !rs.isEmpty()); + + msgs = getChatMessages(rs); + + assertTrue("Messages too few - findByEndDate", msgs.size() >= 3); + + /** + * This must find also many messages but atleast one + */ + rs = msgHistoryService.findByKeywords( + room, + new String[]{"test", "word2"}); + + assertTrue("Nothing found findByKeywords", !rs.isEmpty()); + msgs = getChatMessages(rs); + assertTrue("Messages too few - findByKeywords", msgs.size() >= 1); + + /** + * Nothing to be found + */ + rs = msgHistoryService.findByKeywords( + room, + new String[]{"test1", "word2"}); + + assertFalse("Something found findByKeywords", !rs.isEmpty()); + + /** + * must find 2 messages + */ + rs = msgHistoryService.findByPeriod( + room, controlDate1, controlDate2); + + assertTrue("Nothing found findByPeriod", !rs.isEmpty()); + + msgs = getChatMessages(rs); + + assertEquals("Messages must be 2", msgs.size(), 2); + + assertTrue("Message no found", + msgs.contains(messagesToSend[1].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[2].getContent())); + + /** + * must find 1 record + */ + rs = msgHistoryService.findByPeriod( + room, controlDate1, controlDate2, new String[]{"word2"}); + + assertTrue("Nothing found findByPeriod", !rs.isEmpty()); + + msgs = getChatMessages(rs); + + assertEquals("Messages must be 1", msgs.size(), 1); + assertTrue("Message no found", + msgs.contains(messagesToSend[1].getContent())); + + /** + * must find 2 records + */ + rs = msgHistoryService.findByStartDate(room, controlDate2); + + assertTrue("Nothing found findByStartDate", !rs.isEmpty()); + msgs = getChatMessages(rs); + assertEquals("Messages must be 2", msgs.size(), 2); + assertTrue("Message no found", + msgs.contains(messagesToSend[3].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[4].getContent())); + + /** + * Must return exactly the last 3 messages + */ + rs = msgHistoryService.findLast(room, 3); + + assertTrue("Nothing found 8", !rs.isEmpty()); + msgs = getChatMessages(rs); + assertEquals("Messages must be 3", msgs.size(), 3); + assertTrue("Message no found", + msgs.contains(messagesToSend[2].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[3].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[4].getContent())); + + /** + * Must return exactly the 3 messages after controlDate1 + */ + rs = msgHistoryService.findFirstMessagesAfter(room, controlDate1, 3); + + assertTrue("Nothing found 9", !rs.isEmpty()); + msgs = getChatMessages(rs); + assertEquals("Messages must be 3", msgs.size(), 3); + assertTrue("Message no found", + msgs.contains(messagesToSend[1].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[2].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[3].getContent())); + + /** + * Must return exactly the 3 messages before controlDate2 + */ + rs = msgHistoryService.findLastMessagesBefore(room, controlDate2, 3); + + assertTrue("Nothing found 10", !rs.isEmpty()); + msgs = getChatMessages(rs); + assertEquals("Messages must be 3", msgs.size(), 3); + assertTrue("Message no found", + msgs.contains(messagesToSend[0].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[1].getContent())); + assertTrue("Message no found", + msgs.contains(messagesToSend[2].getContent())); + } /** * Removes the locally stored contact list copy. The purpose of this is to @@ -383,7 +619,7 @@ private Vector getMessages(Collection rs) Iterator iter = rs.iterator(); while (iter.hasNext()) { - Object item = (Object) iter.next(); + Object item = iter.next(); if(item instanceof MessageDeliveredEvent) result.add(((MessageDeliveredEvent)item).getSourceMessage().getContent()); else @@ -393,6 +629,25 @@ private Vector getMessages(Collection rs) return result; } + + private Vector getChatMessages(Collection rs) + { + Vector result = new Vector(); + Iterator iter = rs.iterator(); + while (iter.hasNext()) + { + Object item = iter.next(); + if(item instanceof ChatRoomMessageDeliveredEvent) + result.add(((ChatRoomMessageDeliveredEvent)item). + getMessage().getContent()); + else + if(item instanceof ChatRoomMessageReceivedEvent) + result.add(((ChatRoomMessageReceivedEvent)item). + getMessage().getContent()); + } + + return result; + } private void dumpResult(QueryResultSet rs)