package org.rr.jeborker.gui.action;
import static org.rr.jeborker.app.JeboorkerConstants.SUPPORTED_MIMES.MIME_EPUB;
import static org.rr.jeborker.app.JeboorkerConstants.SUPPORTED_MIMES.MIME_MOBI;
import static org.rr.jeborker.app.JeboorkerConstants.SUPPORTED_MIMES.MIME_AZW;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Action;
import javax.swing.JTable;
import org.rr.commons.mufs.IResourceHandler;
import org.rr.commons.mufs.ResourceHandlerFactory;
import org.rr.jeborker.converter.ConverterFactory;
import org.rr.jeborker.db.item.EbookPropertyItem;
import org.rr.jeborker.gui.MainController;
import org.rr.jeborker.metadata.IMetadataReader;
import org.rr.jeborker.metadata.MetadataHandlerFactory;
import org.rr.jeborker.metadata.MetadataProperty;
import skt.swing.search.FindAction;
import skt.swing.search.TableFindAction;
public class ActionFactory {
private static FindAction tableFindAction;
private static interface ActionType {
/**
* Get the class for the action represented by this enum entry.
*/
Class<? extends Action> getActionClass();
/**
* Tells if the action is able to handle the given resource.
* @param resourceHandler The resource to be tested.
* @return <code>true</code> if the resource can be handled by the action or <code>false</code> if not.
*/
boolean canHandle(final EbookPropertyItem item);
boolean canHandle(final IResourceHandler resourceHandler);
/**
* Tells if the action is able to handle multiple selections.
* @return <code>true</code> if multi select is supported and <code>false</code> otherwise.
*/
boolean hasMultipleSelectionSupport();
}
public static enum COMMON_ACTION_TYPES {
ADD_BASE_PATH_ACTION, REMOVE_BASE_PATH_ACTION, REFRESH_BASE_PATH_ACTION, SHOW_HIDE_BASE_PATH_ACTION, REFRESH_ENTRY_ACTION, QUIT_ACTION, SEARCH_ACTION, REMOVE_METADATA_ENTRY_ACTION, SAVE_METADATA_ACTION, SYNC_FOLDER_ACTION, OPEN_FOLDER_ACTION, NEW_FOLDER_ACTION,
OPEN_FILE_ACTION, RENAME_FILE_ACTION, DELETE_FILE_ACTION, VIEW_LOG_MONITOR_ACTION, VIEW_ABOUT_DIALOG_ACTION, SHOW_METADATA_DOWNLOAD_ACTION, SHOW_PDF_SCISSORS_ACTION, SHOW_PREFERENCE_DIALOG_ACTION, COPY_TO_CLIPBOARD_ACTION, PASTE_FROM_CLIPBOARD_ACTION, FILE_SYSTEM_REFRESH_ACTION, FILE_SYSTEM_COLLAPSE_ALL_ACTION, FILE_SYSTEM_IMPORT_ACTION, MOVE_BETWEEN_BASE_FOLDER_ACTION,
CHANGE_LOOK_AND_FEEL_ACTION, MERGE_DOCUMENT_ACTION
}
public static enum DYNAMIC_ACTION_TYPES implements ActionType {
SET_COVER_FROM_FILE_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SetCoverFromFileAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return MetadataHandlerFactory.hasCoverWriterSupport(item.getResourceHandler());
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
SET_COVER_FROM_DOWNLOAD_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SetCoverFromDownload.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return MetadataHandlerFactory.hasCoverWriterSupport(item.getResourceHandler());
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
SET_COVER_FROM_CLIPBOARD_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SetCoverFromClipboardAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
DataFlavor[] availableDataFlavors = c.getAvailableDataFlavors();
for(DataFlavor flavor : availableDataFlavors) {
if(flavor.equals(DataFlavor.imageFlavor)) {
return true;
}
}
return false;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
SET_COVER_FROM_EBOOK_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SetCoverFromEbook.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
String mime = item.getMimeType();
if(mime != null) {
if(mime.equals(MIME_EPUB.getMime()) || mime.equals(MIME_MOBI.getMime()) || mime.equals(MIME_AZW.getMime())) {
return MetadataHandlerFactory.hasCoverWriterSupport(item.getResourceHandler());
}
}
return false;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return false;
}
},
SAVE_COVER_TO_FILE_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SaveCoverToFileAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return MainController.getController().getImageViewerResource() != null;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return false;
}
}, SAVE_COVER_TO_CLIPBOARD_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return SaveCoverToClipboardAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return MainController.getController().getImageViewerImage() != null;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return false;
}
},
EDIT_PLAIN_METADATA_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return EditPlainMetadataAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return MetadataHandlerFactory.hasPlainMetadataSupport(item.getResourceHandler());
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
REFRESH_ENTRY_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return RefreshEntryAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return true;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
DELETE_FILE_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return DeleteFileAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return item.getResourceHandler().exists();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.exists();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
RENAME_FILE_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return RenameFileAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return item.getResourceHandler().exists();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.exists();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
COPY_TO_DROPBOX_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return CopyToDropboxApiFolderAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return item.getResourceHandler().isFileResource();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.isFileResource();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},COPY_TO_PUSHBULLET_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return CopyToPushbulletApiFolderAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return item.getResourceHandler().isFileResource();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.isFileResource();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
COPY_TO_TARGET_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return CopyToTargetAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return item.getResourceHandler().isFileResource();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.isFileResource();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
COPY_TO_CLIPBOARD_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return CopyToClipboardAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return true;
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return resourceHandler.isFileResource();
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
},
PASTE_FROM_CLIPBOARD_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return PasteFromClipboardAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return PasteFromClipboardAction.hasValidClipboardContent() &&
item.getResourceHandler().isFileResource();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return PasteFromClipboardAction.hasValidClipboardContent();
}
@Override
public boolean hasMultipleSelectionSupport() {
return false;
}
},
CONVERT_EBOOK_ACTION {
@Override
public Class<? extends Action> getActionClass() {
return ConvertEbookAction.class;
}
@Override
public boolean canHandle(EbookPropertyItem item) {
return !ConverterFactory.getConverter(item.getResourceHandler()).isEmpty();
}
@Override
public boolean canHandle(IResourceHandler resourceHandler) {
return false;
}
@Override
public boolean hasMultipleSelectionSupport() {
return true;
}
}
}
public static ApplicationAction getAction(COMMON_ACTION_TYPES type, ActionCallback callback, String text) {
return getAction(type, text, callback);
}
public static ApplicationAction getAction(COMMON_ACTION_TYPES type, String text, ActionCallback callback) {
Action action = null;
switch(type) {
case ADD_BASE_PATH_ACTION:
action = new AddBasePathAction(text);
break;
case REMOVE_BASE_PATH_ACTION:
action = new RemoveBasePathAction(text);
break;
case REFRESH_BASE_PATH_ACTION:
action = new RefreshBasePathAction(text);
break;
case SHOW_HIDE_BASE_PATH_ACTION:
action = new ShowHideBasePathAction(text);
break;
case REFRESH_ENTRY_ACTION:
action = new RefreshEntryAction(text);
break;
case QUIT_ACTION:
action = new QuitAction(text);
break;
case SEARCH_ACTION:
action = new SearchAction();
break;
case REMOVE_METADATA_ENTRY_ACTION:
action = RemoveMetadataEntryAction.getInstance();
break;
case SAVE_METADATA_ACTION:
action = SaveMetadataAction.getInstance();
break;
case SYNC_FOLDER_ACTION:
action = SyncFolderAction.getInstance();
break;
case OPEN_FOLDER_ACTION:
action = new OpenFolderAction(text);
break;
case NEW_FOLDER_ACTION:
action = new NewFolderAction(text);
break;
case OPEN_FILE_ACTION:
action = new OpenFileAction(text);
setEnabledForFile(text, action);
break;
case RENAME_FILE_ACTION:
action = new RenameFileAction(text);
setEnabledForFile(text, action);
break;
case DELETE_FILE_ACTION:
action = new DeleteFileAction(text);
break;
case VIEW_LOG_MONITOR_ACTION:
action = new ShowLogDialogAction(text);
break;
case VIEW_ABOUT_DIALOG_ACTION:
action = new ShowAboutDialogAction();
break;
case CHANGE_LOOK_AND_FEEL_ACTION:
action = new ChangeLookAndFeelAction(text);
break;
case SHOW_METADATA_DOWNLOAD_ACTION:
action = new ShowMetadataDownloadDialogAction(text);
break;
case SHOW_PDF_SCISSORS_ACTION:
action = new ShowPdfScissorsAction(text);
break;
case SHOW_PREFERENCE_DIALOG_ACTION:
action = new ShowPreferenceDialogAction(text);
break;
case MERGE_DOCUMENT_ACTION:
action = new MergeDocumentAction(text);
break;
case COPY_TO_CLIPBOARD_ACTION:
action = new CopyToClipboardAction();
break;
case PASTE_FROM_CLIPBOARD_ACTION:
action = new PasteFromClipboardAction(text);
if(!PasteFromClipboardAction.hasValidClipboardContent()) {
action.setEnabled(false);
}
break;
case FILE_SYSTEM_REFRESH_ACTION:
action = new FileSystemTreeRefreshAction(text);
break;
case FILE_SYSTEM_COLLAPSE_ALL_ACTION:
action = new FileSystemCollapseAllAction(text);
break;
case FILE_SYSTEM_IMPORT_ACTION:
action = new FileSystemImportAction(text);
break;
case MOVE_BETWEEN_BASE_FOLDER_ACTION:
action = new MoveBetweenBaseFolderAction(text);
break;
}
if(action != null) {
return ApplicationAction.getInstance(action, callback);
}
return null;
}
public static ApplicationAction getAction(final COMMON_ACTION_TYPES type, final String text) {
return getAction(type, text, null);
}
/**
* Set the given action to disabled if the given <code>text</code>did not represents a file.
* @param text A resource which can be parsed into a file.
* @param action The action which should be disabled if the given <code>text</code> is not an existing file.
*/
private static void setEnabledForFile(final String text, Action action) {
IResourceHandler resourceHandler = ResourceHandlerFactory.getResourceHandler(text);
if(resourceHandler != null && !resourceHandler.isFileResource()) {
action.setEnabled(false);
}
}
public static ApplicationAction getActionForResource(final DYNAMIC_ACTION_TYPES type, List<IResourceHandler> resourceHandlers) {
return getActionForResource(type, resourceHandlers, null);
}
public static ApplicationAction getActionForResource(final DYNAMIC_ACTION_TYPES type, List<IResourceHandler> resourceHandlers, ActionCallback callback) {
resourceHandlers = resourceHandlers != null ? resourceHandlers : Collections.<IResourceHandler>emptyList();
//create the resource handle list.
boolean canHandle = true;
for (int i = 0; i< resourceHandlers.size(); i++) {
IResourceHandler resourceHandler = resourceHandlers.get(i);
if(!type.canHandle(resourceHandler)) {
canHandle = false;
}
}
if(!type.hasMultipleSelectionSupport() && resourceHandlers.size() > 1) {
canHandle = false;
}
//test whether the Action is able to handle all given items.
if(resourceHandlers.isEmpty()) {
//no selection
canHandle = false;
}
Action action = new MultiActionWrapper(type.getActionClass(), null, resourceHandlers, null);
if(!canHandle) {
action.setEnabled(false);
}
return ApplicationAction.getInstance(action, callback);
}
public static ApplicationAction getActionForItems(final DYNAMIC_ACTION_TYPES type, final List<EbookPropertyItem> items, int[] refreshRowsAfter) {
return getActionForItems(type, items, refreshRowsAfter, null);
}
/**
* Get the action of the specific type. If the action could not handle all of the given items
* it is disabled.
* @param type The type of action.
* @param items The items to be handled by the actions.
* @return The desired action instance. Never returns <code>null</code>.
*/
public static ApplicationAction getActionForItems(final DYNAMIC_ACTION_TYPES type, final List<EbookPropertyItem> items, int[] refreshRowsAfter, ActionCallback callback) {
final ArrayList<IResourceHandler> resourceHandlers = new ArrayList<>(items.size());
//create the resource handle list.
boolean canHandle = true;
for (EbookPropertyItem item : items) {
resourceHandlers.add(item.getResourceHandler());
if(!type.canHandle(item)) {
canHandle = false;
}
}
if(!type.hasMultipleSelectionSupport() && items.size() > 1) {
canHandle = false;
}
//test whether the Action is able to handle all given items.
if(items.isEmpty()) {
//no selection
canHandle = false;
}
Action action = new MultiActionWrapper(type.getActionClass(), items, resourceHandlers, refreshRowsAfter);
if(!canHandle) {
action.setEnabled(false);
}
return ApplicationAction.getInstance(action, callback);
}
/**
* Get a list of actions - one for each supported metadata entry - which
* allows to add metadata.
* @param properties The metadata from the {@link IMetadataReader} where the actions
* should be created for.
* @return The actions for adding a metadata entry. Never returns <code>null</code>.
*/
public static List<Action> getAddMetadataActions(List<MetadataProperty> properties, EbookPropertyItem item, ActionCallback callback) {
final ArrayList<Action> result = new ArrayList<>();
for (MetadataProperty property : properties) {
AddMetadataAction addMetadataAction = new AddMetadataAction(property, item);
if(!property.isEditable()) {
addMetadataAction.setEnabled(false);
}
result.add(ApplicationAction.getInstance(addMetadataAction, callback));
}
return result;
}
/**
* Get the Action that is used for the find action in the main table.
*/
public static FindAction getTableFindAction(JTable table) {
if(tableFindAction == null) {
tableFindAction = new TableFindAction(table);
}
return tableFindAction;
}
}