/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** All rights reserved **
** **
** This program and the accompanying materials are made available under **
** the terms of the Eclipse Public License v1.0 which accompanies this **
** distribution, and is available at: **
** http://www.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.ui.internal.undo;
import org.eclipse.core.runtime.Assert;
import org.eclipse.osgi.util.NLS;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INews.State;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.INewsDAO;
import org.rssowl.core.persist.reference.NewsReference;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.ui.internal.Controller;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* An instance of {@link IUndoOperation} that allows to undo/redo changing the
* state of News. For example this supports undo/redo of deleting news or
* marking news as read.
*
* @author bpasero
*/
public class NewsStateOperation implements IUndoOperation {
private static final EnumSet<INews.State> SUPPORTED_STATES = EnumSet.of(INews.State.HIDDEN, INews.State.READ, INews.State.UNREAD);
/* Limit when this operation is becoming a long running one */
private static final int LONG_RUNNING_LIMIT = 50;
private final Map<State, List<NewsReference>> fOldStates;
private final State fNewState;
private final int fNewsCount;
private final boolean fOnlyNewNewsAffected;
private final boolean fAffectEquivalentNews;
private final INewsDAO fNewsDao = DynamicDAO.getDAO(INewsDAO.class);
/**
* @param news
* @param newState
* @param affectEquivalentNews
*/
public NewsStateOperation(Collection<INews> news, INews.State newState, boolean affectEquivalentNews) {
Assert.isTrue(SUPPORTED_STATES.contains(newState), Messages.NewsStateOperation_UNSUPPORTED);
fOldStates = CoreUtils.toStateMap(news);
fNewState = newState;
fAffectEquivalentNews = affectEquivalentNews;
fNewsCount = news.size();
fOnlyNewNewsAffected = fOldStates.containsKey(INews.State.NEW) && fOldStates.get(INews.State.NEW).size() == fNewsCount;
}
/*
* @see org.rssowl.ui.internal.undo.IUndoOperation#getName()
*/
public String getName() {
switch (fNewState) {
case HIDDEN:
return NLS.bind(Messages.NewsStateOperation_DELETE_N_NEWS, fNewsCount);
case READ:
return NLS.bind(Messages.NewsStateOperation_MARK_N_READ, fNewsCount);
case UNREAD: {
if (fOnlyNewNewsAffected)
return NLS.bind(Messages.NewsStateOperation_MARK_N_NEW_UNREAD, fNewsCount);
return NLS.bind(Messages.NewsStateOperation_MARK_N_UNREAD, fNewsCount);
}
default:
return Messages.NewsStateOperation_UNSUPPORTED;
}
}
/*
* @see org.rssowl.ui.internal.undo.IUndoOperation#undo()
*/
public void undo() {
Set<Entry<State, List<NewsReference>>> entries = fOldStates.entrySet();
for (Entry<State, List<NewsReference>> entry : entries) {
INews.State oldState = entry.getKey();
List<NewsReference> newsRefs = entry.getValue();
List<INews> resolvedNews = new ArrayList<INews>(newsRefs.size());
for (NewsReference newsRef : newsRefs) {
INews news = newsRef.resolve();
/* Only support Undo for News if state of news is still current */
if (news != null && news.getState() == fNewState)
resolvedNews.add(news);
}
/* Force quick update of saved searches */
Controller.getDefault().getSavedSearchService().forceQuickUpdate();
/* Set old state back to all news */
fNewsDao.setState(resolvedNews, oldState, fAffectEquivalentNews, false);
}
}
/*
* @see org.rssowl.ui.internal.undo.IUndoOperation#redo()
*/
public void redo() {
Set<Entry<State, List<NewsReference>>> entries = fOldStates.entrySet();
for (Entry<State, List<NewsReference>> entry : entries) {
INews.State oldState = entry.getKey();
List<NewsReference> newsRefs = entry.getValue();
List<INews> resolvedNews = new ArrayList<INews>(newsRefs.size());
for (NewsReference newsRef : newsRefs) {
INews news = newsRef.resolve();
/* Only support Undo for News if state of news is still matching the old one */
if (news != null && news.getState() == oldState)
resolvedNews.add(news);
}
/* Force quick update of saved searches */
Controller.getDefault().getSavedSearchService().forceQuickUpdate();
/* Set state back to all news */
fNewsDao.setState(resolvedNews, fNewState, fAffectEquivalentNews, false);
}
}
/*
* @see org.rssowl.ui.internal.undo.IUndoOperation#isLongRunning()
*/
public boolean isLongRunning() {
return fNewsCount > LONG_RUNNING_LIMIT;
}
}