/***********************************************************************************
*
* Copyright (c) 2014 Kamil Baczkowicz
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*
* Kamil Baczkowicz - initial API and implementation and/or initial documentation
*
*/
package pl.baczkowicz.spy.ui.storage;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pl.baczkowicz.spy.ui.search.MessageFilter;
import pl.baczkowicz.spy.common.generated.FormatterDetails;
import pl.baczkowicz.spy.formatting.FormattingManager;
import pl.baczkowicz.spy.messages.FormattedMessage;
/**
* Message store with filtering.
*/
public class FilteredMessageStore<T extends FormattedMessage> extends BasicMessageStoreWithSummary<T>
{
final static Logger logger = LoggerFactory.getLogger(FilteredMessageStore.class);
/** This is the same as 'show' flag on topic summary. */
private final Set<String> browsedTopics = new HashSet<String>();
//private final MessageListWithObservableTopicSummary filteredMessages;
private final MessageListWithObservableTopicSummary<T> allMessages;
private final Set<MessageFilter<T>> messageFilters = new HashSet<>();
public FilteredMessageStore(final MessageListWithObservableTopicSummary<T> allMessages,
final int preferredSize, final int maxSize, final String name, final FormatterDetails messageFormat,
final FormattingManager formattingManager, final int maxPayloadLength)
{
super("filtered-" + name, preferredSize, maxSize, maxPayloadLength, formattingManager);
setFormatter(messageFormat);
//this.filteredMessages = new MessageListWithObservableTopicSummary(preferredSize, maxSize, "filtered-" + name, messageFormat);
this.allMessages = allMessages;
}
public void addMessageFilter(final MessageFilter<T> messageFilter)
{
messageFilters.add(messageFilter);
}
public void removeMessageFilter(final MessageFilter<T> messageFilter)
{
messageFilters.remove(messageFilter);
// TODO: rebuild the store?
}
public void runFilter(final MessageFilter<T> messageFilter)
{
reinitialiseFilteredStore();
}
@Override
public boolean messageFiltersEnabled()
{
for (final MessageFilter<T> filter : messageFilters)
{
if (filter.isActive())
{
return true;
}
}
return false;
}
private void reinitialiseFilteredStore()
{
getMessageList().clear();
logger.trace("[{}] Store reinitialise = {}/{}", allMessages.getName(), allMessages.getMessages().size(), allMessages);
synchronized (allMessages.getMessages())
{
final int size = allMessages.getMessages().size();
for (int i = size - 1; i >= 0; i--)
{
final T message = allMessages.getMessages().get(i);
if (browsedTopics.contains(message.getTopic()) && !filterMessage(message, false))
{
getMessageList().add(message);
}
}
}
}
public boolean filterMessage(final T message, final boolean updateUi)
{
for (final MessageFilter<T> filter : messageFilters)
{
if (filter.filter(message, getMessageList(), updateUi))
{
return true;
}
}
return false;
}
public boolean updateTopicFilter(final String topic, final boolean show)
{
boolean updated = false;
if (show)
{
updated = applyTopicFilter(topic, true);
}
else
{
updated = removeTopicFilter(topic);
}
return updated;
}
public void addAllTopicFilters()
{
removeAllTopicFilters();
synchronized (allMessages.getMessages())
{
for (T message : allMessages.getMessages())
{
browsedTopics.add(message.getTopic());
if (!filterMessage(message, false))
{
getMessageList().add(message);
}
}
}
}
public void removeAllTopicFilters()
{
synchronized (browsedTopics)
{
browsedTopics.clear();
getMessageList().clear();
}
}
public boolean applyTopicFilters(final Collection<String> topics, final boolean recreateStore)
{
synchronized (browsedTopics)
{
boolean updated = false;
for (final String topic : topics)
{
if (!browsedTopics.contains(topic))
{
logger.debug("Adding {} to active filters for {}; recreate = {}", topic, allMessages.getName(), recreateStore);
browsedTopics.add(topic);
updated = true;
}
}
// TODO: optimise
if (updated && recreateStore)
{
logger.warn("Recreating store for topics in {}", allMessages.getName());
reinitialiseFilteredStore();
}
return updated;
}
}
public boolean applyTopicFilter(final String topic, final boolean recreateStore)
{
return applyTopicFilters(Arrays.asList(topic), recreateStore);
}
public boolean removeTopicFilters(final Collection<String> topics)
{
synchronized (browsedTopics)
{
boolean updated = false;
for (final String topic : topics)
{
if (browsedTopics.contains(topic))
{
logger.debug("Removing {} from active filters for {}", topic, allMessages.getName());
browsedTopics.remove(topic);
updated = true;
}
}
if (updated)
{
reinitialiseFilteredStore();
}
return updated;
}
}
private boolean removeTopicFilter(final String topic)
{
return removeTopicFilters(Arrays.asList(topic));
}
public MessageListWithObservableTopicSummary<T> getFilteredMessages()
{
return getMessageList();
}
public Set<String> getBrowsedTopics()
{
return Collections.unmodifiableSet(browsedTopics);
}
}