/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.repository.gui.actions; import java.awt.event.ActionEvent; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import com.rapidminer.gui.operatortree.actions.CutCopyPasteDeleteAction; import com.rapidminer.gui.tools.ProgressThread; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.SwingTools; import com.rapidminer.gui.tools.dialogs.ConfirmDialog; import com.rapidminer.repository.Entry; import com.rapidminer.repository.RepositoryLocation; import com.rapidminer.repository.gui.RepositoryTree; /** * Abstract superclass of actions that are executed on subclasses of {@link Entry}. Automatically * enables/disables itself. * * @author Simon Fischer, Adrian Wilke */ public abstract class AbstractRepositoryAction<T extends Entry> extends ResourceAction { /** the tree to which the action belongs to */ protected final RepositoryTree tree; /** the required selection type for the action to show/enable */ private final Class<T> requiredSelectionType; /** if write access to the repository is needed for this action */ private final boolean needsWriteAccess; private static final long serialVersionUID = -6415235351430454776L; public AbstractRepositoryAction(RepositoryTree tree, Class<T> requiredSelectionType, boolean needsWriteAccess, String i18nKey) { super(true, i18nKey); this.tree = tree; this.requiredSelectionType = requiredSelectionType; this.needsWriteAccess = needsWriteAccess; setEnabled(false); } @Override protected void update(boolean[] conditions) { // we have our own mechanism to enable/disable actions, // so ignore ConditionalAction mechanism } /** * Enables action, if every entry exists and can be written if needed. */ public void enable() { // Do not treat entries, whose are already included in selected folders List<Entry> entries = removeIntersectedEntries(tree.getSelectedEntries()); boolean enable = true; for (Entry entry : entries) { if (entry == null) { enable = false; break; } if (!requiredSelectionType.isInstance(entry)) { enable = false; break; } if (needsWriteAccess && entry.isReadOnly()) { enable = false; break; } } if (entries.isEmpty()) { enable = false; } setEnabled(enable); } @Override public void actionPerformed(ActionEvent e) { List<Entry> entries = tree.getSelectedEntries(); // Deletion of elements if (e.getActionCommand().equals(DeleteRepositoryEntryAction.I18N_KEY) || e.getActionCommand().equals(CutCopyPasteDeleteAction.DELETE_ACTION_COMMAND_KEY)) { if (entries.size() == 1) { if (SwingTools.showConfirmDialog("file_chooser.delete", ConfirmDialog.YES_NO_OPTION, entries.get(0).getName()) != ConfirmDialog.YES_OPTION) { return; } } else { if (SwingTools.showConfirmDialog("file_chooser.delete_multiple", ConfirmDialog.YES_NO_OPTION, entries.size()) != ConfirmDialog.YES_OPTION) { return; } } final List<Entry> remainingEntries = removeIntersectedEntries(tree.getSelectedEntries()); ProgressThread progressThread = new ProgressThread(DeleteRepositoryEntryAction.I18N_KEY) { /** Total progress of progress listener bar */ private int progressListenerCompleted = 0; /** Step size for single entry operation */ private final int PROGRESS_LISTENER_SINGLE_STEP_SIZE = 1; @Override public void run() { // Initialize progress listener getProgressListener().setTotal(remainingEntries.size() * PROGRESS_LISTENER_SINGLE_STEP_SIZE); getProgressListener().setCompleted(progressListenerCompleted); for (Entry entry : remainingEntries) { actionPerformed(requiredSelectionType.cast(entry)); progressListenerCompleted += PROGRESS_LISTENER_SINGLE_STEP_SIZE; getProgressListener().setCompleted(progressListenerCompleted); } getProgressListener().complete(); } }; progressThread.setShowDialogTimerDelay(200); progressThread.setStartDialogShowTimer(true); progressThread.start(); } else { // Do not treat entries, whose are already included in selected folders entries = removeIntersectedEntries(tree.getSelectedEntries()); for (Entry entry : entries) { actionPerformed(requiredSelectionType.cast(entry)); } } } public abstract void actionPerformed(T cast); /** * Removes entries from list, which are already included in parent entries * * Example: [/1/2/3, /1, /1/2] becomes [/1] */ protected List<Entry> removeIntersectedEntries(List<Entry> entries) { // Get locations of entries List<RepositoryLocation> locations = new LinkedList<>(); for (Entry entry : entries) { locations.add(entry.getLocation()); } // Remove intersected locations locations = RepositoryLocation.removeIntersectedLocations(locations); // Remove entries of intersected locations Iterator<Entry> entryIt = entries.iterator(); while (entryIt.hasNext()) { if (!locations.contains(entryIt.next().getLocation())) { entryIt.remove(); } } return entries; } }