package org.rr.jeborker.gui.action;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import org.rr.commons.log.LoggerFactory;
import org.rr.commons.mufs.IResourceHandler;
import org.rr.commons.mufs.ResourceHandlerFactory;
import org.rr.commons.utils.ArrayUtils;
import org.rr.commons.utils.StringUtil;
import org.rr.jeborker.app.FileRefreshBackground;
import org.rr.jeborker.app.FileWatchService;
import org.rr.jeborker.app.JeboorkerConstants;
import org.rr.jeborker.app.JeboorkerConstants.SUPPORTED_MIMES;
import org.rr.jeborker.app.preferences.APreferenceStore;
import org.rr.jeborker.app.preferences.PreferenceStoreFactory;
import org.rr.jeborker.db.DefaultDBManager;
import org.rr.jeborker.db.item.EbookPropertyItem;
import org.rr.jeborker.db.item.EbookPropertyItemUtils;
import org.rr.jeborker.gui.MainController;
import org.rr.jeborker.gui.MainMenuBarController;
import org.rr.jeborker.gui.MainMonitor;
import org.rr.jeborker.gui.model.EbookPropertyDBTableModel;
import org.rr.jeborker.gui.model.EbookSheetPropertyModel;
import org.rr.jeborker.gui.model.ReloadableTableModel;
import org.rr.jeborker.metadata.MetadataProperty;
import com.j256.ormlite.stmt.Where;
import com.l2fprod.common.propertysheet.Property;
public class ActionUtils {
/**
* Adds a metadata item to the sheet.
* @param property The property to be added.
*/
static Property addMetadataItem(final MetadataProperty property, final EbookPropertyItem item) {
final Property createProperty = EbookSheetPropertyModel.createProperty(property.clone(), Collections.singletonList(item), 0);
final MainController controller = MainController.getController();
controller.addMetadataProperty(createProperty);
return createProperty;
}
/**
* Shutdown the application.
*/
static void quit() {
MainController.getController().dispose();
FileWatchService.shutdownWatchService();
try {
DefaultDBManager.getInstance().shutdown();
} catch(Exception e1) {
LoggerFactory.logWarning(ActionUtils.class, "Database shutdown failed.", e1);
}
System.exit(0);
}
/**
* Refreshes the entries for the given handler.
* @param resourceLoader The handler of the entry to be refreshed.
*/
static void refreshEntry(final IResourceHandler resourceLoader) {
final List<EbookPropertyItem> items = EbookPropertyItemUtils.getEbookPropertyItemByResource(resourceLoader);
Iterator<EbookPropertyItem> iterator = items.iterator();
if(iterator.hasNext()) {
EbookPropertyItem item = iterator.next();
refreshEbookPropertyItem(item, resourceLoader);
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
refreshFileSystemResourceParent(resourceLoader);
}
});
}
}
/**
* Refresh the given {@link EbookPropertyItem}. Does also persist it to the db!
* @param item The item to be refreshed
* @param resourceLoader The IResourceHandler for the given item. Can be <code>null</code>.
*/
static void refreshEbookPropertyItem(final EbookPropertyItem item, final IResourceHandler resourceHandler) {
final IResourceHandler refreshResourceHandler;
if(resourceHandler == null) {
refreshResourceHandler = ResourceHandlerFactory.getResourceHandler(item.getFile());
} else {
refreshResourceHandler = resourceHandler;
}
//remove the entry from db and view.
if(!refreshResourceHandler.exists()) {
ActionUtils.removeEbookPropertyItem(item);
return;
} else {
EbookPropertyItemUtils.refreshEbookPropertyItem(item, refreshResourceHandler, true);
DefaultDBManager.getInstance().updateObject(item);
if(isSelectedItem(item)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MainController.getController().refreshTableSelectedItem(true);
refreshFileSystemResourceParent(refreshResourceHandler);
}
});
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ReloadableTableModel model = MainController.getController().getModel();
int row = model.searchRow(item);
MainController.getController().refreshTableItem(new int[] {row}, false);
refreshFileSystemResourceParent(refreshResourceHandler);
}
});
}
}
}
/**
* Tests if the given item is a selected one in the view.
* @param item The item to be tested if it's selected.
* @return <code>true</code> if the given item is selected in the view and false otherwise.
*/
private static boolean isSelectedItem(final EbookPropertyItem item) {
List<EbookPropertyItem> selectedEbookPropertyItems = MainController.getController().getSelectedEbookPropertyItems();
for(EbookPropertyItem selected : selectedEbookPropertyItems) {
if(item.equals(selected)) {
return true;
}
}
return false;
}
/**
* Toggles the visibility of the given base path entry. If it's visible
* it's set to hide an other way round.
* @param path The path to be toggled.
*/
public static void toggleBasePathVisibility(String path) {
final boolean isShow = MainMenuBarController.getController().isShowHideBasePathStatusShow(path);
setBasePathVisibility(path, !isShow);
}
/**
* Sets the visibility of the given base path.
* @param path path which visibility should be set.
* @param show <code>true</code> if the base path should be shown and <code>false</code> for hide it.
*/
public static void setBasePathVisibility(final String path, boolean show) {
final String queryIdentifier = ShowHideBasePathAction.class.getName() + "_" + path;
final MainController controller = MainController.getController();
try {
EbookPropertyDBTableModel model = controller.changeToDatabaseModel();
model.removeWhereCondition(queryIdentifier); //remove possibly existing queries.
if(!show) {
model.addWhereCondition(new EbookPropertyDBTableModel.EbookPropertyDBTableModelQuery() {
@Override
public String getIdentifier() {
return queryIdentifier;
}
@Override
public void appendQuery(Where<EbookPropertyItem, EbookPropertyItem> where) throws SQLException {
where.ne("basePath", path);
}
});
}
MainMenuBarController.getController().setShowHideBasePathStatusShow(path, show);
} catch (Exception ex) {
LoggerFactory.log(Level.WARNING, ActionUtils.class, "Path " + path, ex);
} finally {
controller.getEbookTableHandler().refreshTable();
}
}
/**
* Adds the given item to the database and to the ui.
* @param item The item to be added.
*/
public static void addAndStoreEbookPropertyItem(EbookPropertyItem item) {
addAndStoreEbookPropertyItem(item, -1);
}
/**
* Adds the given item to the database and to the ui.
* @param item The item to be added.
* @param row The row where the item should be added to.
*/
public static void addAndStoreEbookPropertyItem(EbookPropertyItem item, int row) {
MainController.getController().getProgressMonitor().setMessage(Bundle.getFormattedString("AddBasePathAction.add", item.getFileName()));
storeEbookPropertyItem(item);
addEbookPropertyItem(item, row);
}
/**
* Stores the given {@link EbookPropertyItem} in the database.
* @param item The database item to be stored.
*/
private static void storeEbookPropertyItem(EbookPropertyItem item) {
DefaultDBManager.getInstance().storeObject(item);
}
/**
* Adds the given {@link EbookPropertyItem} to the ui model.
* @param item The item to be added.
* @param row The row where the item should be added. Can be -1 if it should be attached somewhere.
*/
public static void addEbookPropertyItem(final EbookPropertyItem item, final int row) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MainController.getController().addEbookPropertyItem(item, row);
}
});
}
/**
* Deletes the given item from the database and the view.
* @param item The item to be deleted.
*/
public static void removeEbookPropertyItem(final EbookPropertyItem item) {
final MainMonitor progressMonitor = MainController.getController().getProgressMonitor();
final MainController controller = MainController.getController();
progressMonitor.setMessage(Bundle.getFormattedString("RemoveBasePathAction.deleting", item.getFileName()));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
boolean removed = controller.removeEbookPropertyItem(item);
controller.getMainTreeHandler().refreshFileSystemTreeEntry(item.getResourceHandler());
if(!removed) {
DefaultDBManager.getInstance().deleteObject(item);
}
progressMonitor.setMessage(Bundle.getFormattedString("RemoveBasePathAction.deleted", item.getFileName()));
}
});
}
/**
* Tells if this {@link AResourceHandler} instance file format is an image.
* @param force Open the given {@link IResourceHandler} and read magic bytes if the ebook mime could not be detected.
* @return <code>true</code> if the resource is an image or <code>false</code> otherwise.
*/
public static boolean isSupportedEbookFormat(IResourceHandler resource, boolean force) {
if(resource.getFileExtension().equals("tmp")) {
//no tmp files. tmp files are used to save a changed ebook temporary.
return false;
}
if(isSupportedEbookFormatExtension(resource)) {
return true;
}
if(isSupportedEbookFormatMime(resource, force)) {
return true;
}
return false;
}
/**
* user file formats with basic/empty reader support
*/
private static boolean isSupportedEbookFormatExtension(IResourceHandler resource) {
APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE);
String supportedBasicTypes = preferenceStore.getEntryAsString(PreferenceStoreFactory.PREFERENCE_KEYS.BASIC_FILE_TYPES);
String extension = resource.getFileExtension();
if(!extension.isEmpty() && (supportedBasicTypes.startsWith(extension) || supportedBasicTypes.contains("," + extension))) {
return true;
}
return false;
}
private static boolean isSupportedEbookFormatMime(IResourceHandler resource, boolean force) {
final String mime = resource.getMimeType(force);
if(StringUtil.isEmpty(mime)) {
return false;
}
for(SUPPORTED_MIMES supportedMime : JeboorkerConstants.SUPPORTED_MIMES.values()) {
if(supportedMime.getMime().equals(mime)) {
return true;
}
}
return false;
}
public static void moveEbookResources(final List<EbookPropertyItem> sourceEbookPropertyItems, final String basePath, final boolean move) {
FileRefreshBackground.runWithDisabledRefresh(new Runnable() {
@Override
public void run() {
IResourceHandler targetFolderResourceHandler = ResourceHandlerFactory.getResourceHandler(basePath);
List<IResourceHandler> resourcesToRefresh = new ArrayList<>();
for (int i = 0; i < sourceEbookPropertyItems.size(); i++) {
try {
EbookPropertyItem ebookPropertyItem = sourceEbookPropertyItems.get(i);
IResourceHandler sourceResourceHandler = ebookPropertyItem.getResourceHandler();
IResourceHandler targetResourceHandler = ResourceHandlerFactory.getResourceHandler(targetFolderResourceHandler, sourceResourceHandler.getName());
if (!isImportAllowed(sourceResourceHandler, targetResourceHandler)) {
LoggerFactory.log(Level.WARNING, this, "Not allowed to move " + sourceResourceHandler + " to " + targetResourceHandler + ".");
continue;
}
resourcesToRefresh.add(sourceResourceHandler);
transferFile(sourceResourceHandler, targetResourceHandler, move);
ebookPropertyItem.setBasePath(basePath);
ebookPropertyItem.setFile(targetResourceHandler.toFile().getAbsolutePath());
ActionUtils.refreshEbookPropertyItem(ebookPropertyItem, targetResourceHandler);
} catch (Exception ex) {
LoggerFactory.log(Level.WARNING, this, "Failed to move file to " + basePath, ex);
}
}
refreshFileSystemResourceParents(resourcesToRefresh);
}
});
}
public static List<IResourceHandler> importEbookResources(final List<IResourceHandler> sources, final String basePath, final boolean move) {
return importEbookResources(sources, null, basePath, move);
}
public static List<IResourceHandler> importEbookResources(final List<IResourceHandler> sources, final IResourceHandler targetResourceDirectory, final String basePath, final boolean move) {
final List<IResourceHandler> importedResources = new ArrayList<>();
FileRefreshBackground.runWithDisabledRefresh(new Runnable() {
@Override
public void run() {
IResourceHandler targetFolder;
if(targetResourceDirectory != null) {
targetFolder = targetResourceDirectory;
} else {
targetFolder = ResourceHandlerFactory.getResourceHandler(basePath);
}
for (int i = 0; i < sources.size(); i++) {
try {
IResourceHandler sourceResourceHandler = sources.get(i);
IResourceHandler targetResourceHandler = ResourceHandlerFactory.getResourceHandler(targetFolder, sourceResourceHandler.getName());
if (!isImportAllowed(sourceResourceHandler, targetResourceHandler)) {
LoggerFactory.log(Level.WARNING, this, "Not allowed to move " + sourceResourceHandler + " to " + targetResourceHandler + ".");
continue;
}
transferFile(sourceResourceHandler, targetResourceHandler, false);
EbookPropertyItem ebookPropertyItem = EbookPropertyItemUtils.createEbookPropertyItem(targetResourceHandler, ResourceHandlerFactory.getResourceHandler(basePath));
ActionUtils.refreshEbookPropertyItem(ebookPropertyItem, targetResourceHandler);
importedResources.add(targetResourceHandler);
} catch (Exception ex) {
LoggerFactory.log(Level.WARNING, this, "Failed to move file to " + basePath, ex);
}
}
refreshFileSystemResourceParents(sources);
}
});
return importedResources;
}
public static void refreshFileSystemResourceParents(List<IResourceHandler> resources) {
Set<IResourceHandler> alreadyRefreshedParents = new HashSet<>(resources.size());
for (IResourceHandler resourceHandler : resources) {
IResourceHandler parentResource = resourceHandler.getParentResource();
if(!alreadyRefreshedParents.contains(parentResource)) {
refreshFileSystemResourceParent(parentResource);
alreadyRefreshedParents.add(parentResource);
}
}
}
public static void refreshFileSystemResourceParent(IResourceHandler parentResource) {
MainController.getController().getMainTreeHandler().refreshFileSystemTreeEntry(parentResource);
}
private static boolean transferFile(IResourceHandler sourceResource, IResourceHandler targetResource, boolean move) throws IOException {
if(move) {
sourceResource.moveTo(targetResource, false);
} else {
sourceResource.copyTo(targetResource, false);
}
return targetResource.exists();
}
private static boolean isImportAllowed(IResourceHandler sourceResource, IResourceHandler targetResource) {
return sourceResource != null && ActionUtils.isSupportedEbookFormat(sourceResource, true) && !targetResource.exists();
}
public static void applyFilter(final String ... fileNames) {
MainController.getController().changeToDatabaseModel().addWhereCondition(new EbookPropertyDBTableModel.EbookPropertyDBTableModelQuery() {
@Override
public String getIdentifier() {
return getClass().getName();
}
@Override
public void appendQuery(Where<EbookPropertyItem, EbookPropertyItem> where) throws SQLException {
String filter = ArrayUtils.join(fileNames, ",");
LoggerFactory.getLogger().log(Level.INFO, "Apply filter " + filter);
for (int i = 0; i < fileNames.length; i++) {
String fileName = fileNames[i];
if(i == 0) {
where.like("fileName", fileName);
} else {
where.or().like("fileName", fileName);
}
}
}
@Override
public boolean isVolatile() {
return true;
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MainController.getController().getEbookTableHandler().refreshTable();
}
});
}
}