/* ********************************************************************** **
** 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.dialogs.importer;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.persist.pref.DefaultPreferences;
import org.rssowl.core.interpreter.ITypeImporter;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IFolderChild;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INewsBin;
import org.rssowl.core.persist.IPreference;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.IBookMarkDAO;
import org.rssowl.core.persist.pref.IPreferenceScope;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.Controller;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.actions.ReloadTypesAction;
import org.rssowl.ui.internal.dialogs.importer.ImportSourcePage.Source;
import org.rssowl.ui.internal.dialogs.welcome.WelcomeWizard;
import org.rssowl.ui.internal.editors.feed.NewsGrouping;
import org.rssowl.ui.internal.util.ImportUtils;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.views.explorer.BookMarkExplorer;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* A {@link Wizard} to import bookmarks, saved searches and bins with the option
* to also import settings (Labels, Filters, Properties) from OPML. Supports
* importing from local resources as well as remote.
*
* @author bpasero
*/
public class ImportWizard extends Wizard implements IImportWizard {
private ImportSourcePage fImportSourcePage;
private ImportElementsPage fImportElementsPage;
private ImportTargetPage fImportTargetPage;
private ImportOptionsPage fImportOptionsPage;
private final IFolder fTargetFolder;
private String fFileOrWebsite;
private boolean fIsKewordSearch;
private boolean fIsWelcome;
/** Default Constructor */
public ImportWizard() {
this(null, null, false);
}
/*
* @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
*/
public void init(IWorkbench workbench, IStructuredSelection selection) {}
/**
* @param isWelcome if <code>true</code>, this wizard is used from the
* {@link WelcomeWizard}.
*/
public ImportWizard(boolean isWelcome) {
this(null, null, false);
fIsWelcome = isWelcome;
}
/**
* @param targetFolder the target {@link IFolder} to import to or
* <code>null</code> if none.
* @param fileOrWebsite a link to a website to discover feeds on or a file to
* import feeds from.
* @param isKeywordSearch defines if the keyword search should be selected or
* not.
*/
public ImportWizard(IFolder targetFolder, String fileOrWebsite, boolean isKeywordSearch) {
fTargetFolder = targetFolder;
fFileOrWebsite = fileOrWebsite;
fIsKewordSearch = isKeywordSearch;
}
/*
* @see org.eclipse.jface.wizard.Wizard#addPages()
*/
@Override
public void addPages() {
setWindowTitle(Messages.ImportWizard_IMPORT);
/* Page 1: Source to Import */
fImportSourcePage = new ImportSourcePage(fFileOrWebsite, fIsKewordSearch);
addPage(fImportSourcePage);
/* Page 2: Elements to Import */
fImportElementsPage = new ImportElementsPage();
addPage(fImportElementsPage);
/* Page 3: Target to Import */
fImportTargetPage = new ImportTargetPage(fTargetFolder);
addPage(fImportTargetPage);
/* Page 4: Import Options */
fImportOptionsPage = new ImportOptionsPage();
addPage(fImportOptionsPage);
}
/*
* @see org.eclipse.jface.wizard.Wizard#getNextPage(org.eclipse.jface.wizard.IWizardPage)
*/
@Override
public IWizardPage getNextPage(IWizardPage page) {
/* Jump to Options Page if required and skip Target if nothing selected */
if (page instanceof ImportElementsPage && !fImportSourcePage.isRemoteSource() && fImportElementsPage.getFolderChildsToImport().isEmpty() && fImportElementsPage.showOptionsPage())
return fImportOptionsPage;
/* Skip Options Page if not required after Target Page */
if (page instanceof ImportTargetPage && !fImportElementsPage.showOptionsPage())
return null;
return super.getNextPage(page);
}
/*
* @see org.eclipse.jface.wizard.Wizard#performFinish()
*/
@Override
public boolean performFinish() {
/* Directly Return if nothing to import */
if (fImportSourcePage.getSource() == Source.NONE)
return true;
/* Perform Import */
return doImport();
}
/*
* @see org.eclipse.jface.wizard.Wizard#canFinish()
*/
@Override
public boolean canFinish() {
/* Prohibit direct Finish from Sources that require a potential remote connection or include recommended feeds */
if (getContainer().getCurrentPage() == fImportSourcePage) {
if ((fImportSourcePage.getSource() == Source.RESOURCE) || fImportSourcePage.isRemoteSource() || (fImportSourcePage.getSource() == Source.RECOMMENDED))
return false;
}
/* Allow to Finish if nothing should be imported */
if (fImportSourcePage.getSource() == Source.NONE)
return true;
/* Other Pages decide on their own */
return super.canFinish();
}
private boolean doImport() {
/* Collect Elements to Import */
List<IFolderChild> folderChilds = fImportElementsPage.getFolderChildsToImport();
boolean isRSSOwlOPML = isRSSOwlOPMLImport(folderChilds);
if (fImportElementsPage.excludeExisting())
folderChilds = excludeExisting(folderChilds);
/* Check for Errors First */
if (StringUtils.isSet(fImportElementsPage.getErrorMessage())) {
getContainer().showPage(fImportElementsPage);
return false;
}
List<ILabel> labels = fImportElementsPage.getLabelsToImport();
List<ISearchFilter> filters = fImportElementsPage.getFiltersToImport();
List<IPreference> preferences = fImportElementsPage.getPreferencesToImport();
/* Normalize Elements to Import */
CoreUtils.normalize(folderChilds);
/* Get Target Location (may be null) */
IFolder target = fIsWelcome ? null : fImportTargetPage.getTargetLocation();
/* Get Options */
boolean importLabels = fImportOptionsPage.importLabels();
if (!importLabels)
labels = null;
boolean importFilters = fImportOptionsPage.importFilters();
if (!importFilters)
filters = null;
boolean importPreferences = fImportOptionsPage.importPreferences();
if (!importPreferences)
preferences = null;
/* Show warning and ask for confirmation if preferences should be imported */
if (!fIsWelcome && importPreferences && preferences != null && !preferences.isEmpty()) {
MessageDialog dialog = new MessageDialog(getShell(), Messages.ImportWizard_ATTENTION, null, Messages.ImportWizard_PREFERENCE_OVERWRITE, MessageDialog.WARNING, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);
if (dialog.open() != 0)
return false;
}
/* Run Import */
ImportUtils.doImport(target, folderChilds, labels, filters, preferences, !fIsWelcome);
/* Add Default Saved Searches if this is from Welcome Wizard */
if (fIsWelcome && !isRSSOwlOPML && !importLabels && !importFilters && !importPreferences)
addDefaultSearches();
/* Save Settings of Pages */
fImportSourcePage.saveSettings();
/* Ask for a restart if preferences have been imported */
if (importPreferences && preferences != null && !preferences.isEmpty()) {
boolean restart = MessageDialog.openQuestion(getShell(), Messages.ImportWizard_RESTART_RSSOWL, Messages.ImportWizard_RESTART_RSSOWL_INFO);
if (restart) {
BookMarkExplorer explorer = OwlUI.getOpenedBookMarkExplorer();
if (explorer != null)
explorer.saveStateOnDispose(false);
Controller.getDefault().restart();
return true;
}
}
/* Reveal and Select Target Folder */
if (target != null && target.getParent() != null) {
BookMarkExplorer explorer = OwlUI.getOpenedBookMarkExplorer();
if (explorer != null)
explorer.reveal(target, true);
}
/* Reload Imported Elements */
new ReloadTypesAction(new StructuredSelection(folderChilds), OwlUI.getPrimaryShell()).run();
/* Force to rerun saved searches */
JobRunner.runDelayedInBackgroundThread(new Runnable() {
public void run() {
Controller.getDefault().getSavedSearchService().updateSavedSearches(true);
}
});
return true;
}
private boolean isRSSOwlOPMLImport(List<IFolderChild> folderChilds) {
for (IFolderChild child : folderChilds) {
if (child instanceof IFolder && child.getParent() == null) {
IFolder set = (IFolder) child;
if (set.getProperty(ITypeImporter.TEMPORARY_FOLDER) == null)
return true;
}
}
return false;
}
/* Remove existing Bookmarks and Empty Folders */
private List<IFolderChild> excludeExisting(List<IFolderChild> folderChilds) {
IBookMarkDAO dao = DynamicDAO.getDAO(IBookMarkDAO.class);
for (Iterator<IFolderChild> iterator = folderChilds.iterator(); iterator.hasNext();) {
IFolderChild child = iterator.next();
/* Bookmark (exclude if another Bookmark with same Link exists) */
if (child instanceof IBookMark) {
IBookMark bm = (IBookMark) child;
if (dao.exists(bm.getFeedLinkReference()))
iterator.remove();
}
/* Bin (exclude if another Bin with same name Exists at same Location) */
else if (child instanceof INewsBin) {
INewsBin bin = (INewsBin) child;
if (CoreUtils.existsNewsBin(bin))
iterator.remove();
}
/* Search (exclude if another Search with same name Exists at same Location and same Conditions) */
else if (child instanceof ISearchMark) {
ISearchMark search = (ISearchMark) child;
if (CoreUtils.existsSearchMark(search))
iterator.remove();
}
/* Folder */
else if (child instanceof IFolder) {
excludeExisting((IFolder) child);
}
}
/* Exclude Empty Folders */
for (Iterator<IFolderChild> iterator = folderChilds.iterator(); iterator.hasNext();) {
IFolderChild child = iterator.next();
if (child instanceof IFolder && ((IFolder) child).getChildren().isEmpty())
iterator.remove();
}
return folderChilds;
}
/* Remove existing Bookmarks and Empty Folders */
private void excludeExisting(IFolder folder) {
IBookMarkDAO dao = DynamicDAO.getDAO(IBookMarkDAO.class);
List<IFolderChild> children = folder.getChildren();
for (IFolderChild child : children) {
/* Bookmark (exclude if another Bookmark with same Link exists) */
if (child instanceof IBookMark) {
IBookMark bm = (IBookMark) child;
if (dao.exists(bm.getFeedLinkReference()))
folder.removeChild(bm);
}
/* Bin (exclude if another Bin with same name Exists at same Location) */
else if (child instanceof INewsBin) {
INewsBin bin = (INewsBin) child;
if (CoreUtils.existsNewsBin(bin))
folder.removeChild(bin);
}
/* Search (exclude if another Search with same name Exists at same Location and same Conditions) */
else if (child instanceof ISearchMark) {
ISearchMark search = (ISearchMark) child;
if (CoreUtils.existsSearchMark(search))
folder.removeChild(search);
}
/* Folder */
else if (child instanceof IFolder) {
excludeExisting((IFolder) child);
}
}
/* Remove from Parent if Empty Now */
if (folder.getChildren().isEmpty() && folder.getParent() != null)
folder.getParent().removeChild(folder);
}
/*
* @see org.eclipse.jface.wizard.Wizard#needsProgressMonitor()
*/
@Override
public boolean needsProgressMonitor() {
return true;
}
private void addDefaultSearches() {
Set<IFolder> roots = CoreUtils.loadRootFolders();
if (roots.isEmpty())
return;
IFolder root = roots.iterator().next();
IModelFactory factory = Owl.getModelFactory();
String newsEntityName = INews.class.getName();
/* SearchCondition: Unread News */
{
ISearchMark mark = factory.createSearchMark(null, root, Messages.ImportWizard_NEW_UPDATED_NEWS);
mark.setMatchAllConditions(true);
ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, INews.State.UNREAD, INews.State.UPDATED));
}
/* SearchCondition: Todays News */
{
ISearchMark mark = factory.createSearchMark(null, root, Messages.ImportWizard_TODAYS_NEWS);
mark.setMatchAllConditions(true);
ISearchField field1 = factory.createSearchField(INews.AGE_IN_DAYS, newsEntityName);
factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS_LESS_THAN, 1);
}
/* SearchCondition: News with Attachments */
{
ISearchMark mark = factory.createSearchMark(null, root, Messages.ImportWizard_NEWS_WITH_ATTACHMENTS);
mark.setMatchAllConditions(true);
ISearchField field = factory.createSearchField(INews.HAS_ATTACHMENTS, newsEntityName);
factory.createSearchCondition(null, mark, field, SearchSpecifier.IS, true);
}
/* SearchCondition: Sticky News */
{
ISearchMark mark = factory.createSearchMark(null, root, Messages.ImportWizard_STICKY_NEWS);
mark.setMatchAllConditions(true);
ISearchField field = factory.createSearchField(INews.IS_FLAGGED, newsEntityName);
factory.createSearchCondition(null, mark, field, SearchSpecifier.IS, true);
}
/* SearchCondition: News is Labeld */
{
ISearchMark mark = factory.createSearchMark(null, root, Messages.ImportWizard_LABELED_NEWS);
IPreferenceScope preferences = Owl.getPreferenceService().getEntityScope(mark);
preferences.putInteger(DefaultPreferences.BM_NEWS_GROUPING, NewsGrouping.Type.GROUP_BY_LABEL.ordinal());
ISearchField field = factory.createSearchField(INews.LABEL, newsEntityName);
factory.createSearchCondition(null, mark, field, SearchSpecifier.IS, "*"); //$NON-NLS-1$
}
DynamicDAO.save(root);
}
}