package org.rr.jeborker.gui.action;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.rr.commons.log.LoggerFactory;
import org.rr.commons.mufs.IResourceHandler;
import org.rr.commons.mufs.ResourceHandlerFactory;
import org.rr.commons.mufs.ResourceHandlerUtils;
import org.rr.commons.mufs.ResourceNameFilter;
import org.rr.commons.swing.SwingUtils;
import org.rr.jeborker.app.preferences.APreferenceStore;
import org.rr.jeborker.app.preferences.PreferenceStoreFactory;
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.resources.ImageResourceBundle;
/**
* Add a folder action.
*/
class AddBasePathAction extends AbstractAction {
private static final long serialVersionUID = -9066575818229620987L;
private String path;
AddBasePathAction(String text) {
String name = Bundle.getString("AddBasePathAction.name");
if(text==null) {
putValue(Action.NAME, SwingUtils.removeMnemonicMarker(name));
} else {
putValue(Action.NAME, text);
if(ResourceHandlerFactory.hasResourceHandler(text)) {
path = text;
}
}
putValue(Action.SMALL_ICON, ImageResourceBundle.getResourceAsImageIcon("add_16.png"));
// putValue(Action.LARGE_ICON_KEY, ImageResourceBundle.getResourceAsImageIcon("add_22.png"));
putValue(MNEMONIC_KEY, SwingUtils.getMnemonicKeyCode(name));
putValue(SHORT_DESCRIPTION, Bundle.getString("AddBasePathAction.tooltip")); //tooltip
}
@Override
public void actionPerformed(ActionEvent e) {
final MainController controller = MainController.getController();
String path = this.path;
controller.getEbookTableHandler().clearSelection();
if(this.path != null && this.path.length() > 0) {
IResourceHandler selectedDirectory = ResourceHandlerFactory.getResourceHandler(path);
addBasePath(controller, selectedDirectory, path);
} else {
final List<File> directorySelections = controller.getDirectorySelection();
for (File directorySelection : directorySelections) {
IResourceHandler selectedDirectory = ResourceHandlerFactory.getResourceHandler(directorySelection);
addBasePath(controller, selectedDirectory, selectedDirectory.toString());
}
}
System.gc();
}
private void addBasePath(final MainController controller, final IResourceHandler selectedDirectory, String path) {
final APreferenceStore preferenceStore = PreferenceStoreFactory.getPreferenceStore(PreferenceStoreFactory.DB_STORE);
if(selectedDirectory!=null) {
controller.getProgressMonitor().monitorProgressStart(Bundle.getString("AddBasePathAction.message"));
String messageFinished = Bundle.getString("AddBasePathAction.finished");
try {
//only attach the new path if it is not a part of an already configured path.
if(!isAlreadyExistingBasePath(preferenceStore.getBasePath(), path)) {
preferenceStore.addBasePath(path); //add path to preferences
int count = readEbookFilesToDB(selectedDirectory);
messageFinished = Bundle.getFormattedString("AddBasePathAction.finishedCount", String.valueOf(count));
} else {
messageFinished = Bundle.getFormattedString("AddBasePathAction.duplicatePathEntry", path);
}
} catch(Throwable t) {
LoggerFactory.log(Level.WARNING, this, "Adding " + path + " has failed", t);
}
controller.getProgressMonitor().monitorProgressStop(messageFinished);
controller.getEbookTableHandler().refreshTable();
controller.getMainTreeHandler().refreshBasePathTree();
}
}
/**
* Tests if the first path is part of the second or the second path is part of the first
* @param existing A list of path to be compared
* @param path The path to be compared with the list
* @return <code>true</code> if the path match to another or <code>false</code> otherwise.
*/
private boolean isAlreadyExistingBasePath(List<String> existing, String path) {
path = path.replace('\\', '/');
if(!path.endsWith("/")) {
path += "/";
}
for (Iterator<String> iterator = existing.iterator(); iterator.hasNext();) {
String existingEntry = iterator.next();
existingEntry = existingEntry.replace('\\', '/');
if(!existingEntry.endsWith("/")) {
existingEntry += "/";
}
if(path.startsWith(existingEntry) || existingEntry.startsWith(path)) {
return true;
}
}
return false;
}
/**
* Read all ebook files recursive and stores them directly to the database.
* @param baseFolder The folder where the ebook search should be started.
*/
static int readEbookFilesToDB(final IResourceHandler baseFolder) {
final HashSet<String> path = new HashSet<>();
int count = ResourceHandlerUtils.readAllFilesFromBasePath(baseFolder, new ResourceNameFilter() {
@Override
public boolean accept(IResourceHandler resource) {
if(resource.isFileResource() && ActionUtils.isSupportedEbookFormat(resource, true)) {
try {
final EbookPropertyItem item = EbookPropertyItemUtils.createEbookPropertyItem(resource, baseFolder);
ActionUtils.addAndStoreEbookPropertyItem(item);
path.add(resource.getParentResource().toString());
return true;
} catch(Throwable e) {
LoggerFactory.getLogger(this).log(Level.SEVERE, "Failed adding resource " + resource, e);
}
}
return false;
}
});
EbookPropertyItemUtils.storePathElements(path);
return count;
}
}