/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.TimeZone; import org.apache.vysper.xml.fragment.Renderer; import org.apache.vysper.xmpp.modules.extension.xep0045_muc.stanzas.History; import org.apache.vysper.xmpp.stanza.Stanza; /** * The discussion history for a room * * @author The Apache MINA Project (dev@mina.apache.org) */ public class DiscussionHistory { public static final int DEFAULT_HISTORY_SIZE = 20; private int maxItems = DEFAULT_HISTORY_SIZE; private DiscussionMessage subjectMessage; private List<DiscussionMessage> items = new ArrayList<DiscussionMessage>(); public void append(Stanza stanza, Occupant sender) { append(stanza, sender, Calendar.getInstance(TimeZone.getTimeZone("UTC"))); } public void append(Stanza stanza, Occupant sender, Calendar timestamp) { synchronized (items) { DiscussionMessage discMsg = new DiscussionMessage(stanza, sender, timestamp); if (discMsg.hasSubject() && !discMsg.hasBody()) { subjectMessage = discMsg; } else { items.add(discMsg); } // check if size is over limits if (getSize() > maxItems) { items.remove(0); } } } private int getSize() { int size = items.size(); if (subjectMessage != null) size++; return size; } public List<Stanza> createStanzas(Occupant receiver, boolean includeJid, History history) { synchronized (items) { int maxstanzas = history != null && history.getMaxStanzas() != null ? history.getMaxStanzas() : -1; int maxchars = history != null && history.getMaxChars() != null ? history.getMaxChars() : -1; int seconds = history != null && history.getSeconds() != null ? history.getSeconds() : -1; List<Stanza> stanzas = new ArrayList<Stanza>(); if (maxchars == 0 || maxstanzas == 0 || seconds == 0) { // quick return for no-stanza requests } else { int counter = 0; int totalChars = 0; List<DiscussionMessage> itemsWithSubject = new ArrayList<DiscussionMessage>(items); // add subject if one is provided if (subjectMessage != null) { itemsWithSubject.add(subjectMessage); } // the timestamp at which "seconds" start filtering from long secondsLimit = -1; if (seconds != -1) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.add(Calendar.SECOND, -seconds); secondsLimit = cal.getTimeInMillis(); } // now add all messages, as long as the predicated are fulfilled // first, do this in reverse order so that older messages are filtered out for (int i = itemsWithSubject.size() - 1; i > -1; i--) { DiscussionMessage item = itemsWithSubject.get(i); Stanza stanza = item.createStanza(receiver, includeJid); counter++; if (secondsLimit != -1 && secondsLimit > item.getTimestamp().getTimeInMillis()) { // too old, break break; } if (history != null && history.getSince() != null && history.getSince().after(item.getTimestamp())) { // too old, break break; } // only count chars if needed if (maxchars != -1) { totalChars += new Renderer(stanza).getComplete().length(); if (totalChars > maxchars) { break; } } // checks after this line will include the last stanza stanzas.add(stanza); if (maxstanzas != -1 && counter == maxstanzas) { // max number of stanzas reached, return break; } } } // reverse list so that the oldest message is first Collections.reverse(stanzas); return stanzas; } } }