All Downloads are FREE. Search and download functionalities are using the official Maven repository.

application.ui.impl.export.PefExportProviderImpl Maven / Gradle / Ivy

package application.ui.impl.export;

import java.io.File;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.daisy.braille.utils.api.factory.FactoryProperties;
import org.daisy.braille.utils.api.table.TableCatalog;
import org.daisy.dotify.studio.api.ExportAction;
import org.daisy.dotify.studio.api.ExportActionDescription;
import org.daisy.dotify.studio.api.ExportActionProvider;
import org.daisy.streamline.api.media.FileDetails;

import application.common.FactoryPropertiesAdapter;
import application.common.Settings;
import application.common.Settings.Keys;
import application.ui.preview.FileDetailsCatalog;
import javafx.concurrent.Task;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceDialog;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Window;

/**
 * Provides an export action provider for PEF-files.
 * @author Joel Håkansson
 */
public class PefExportProviderImpl implements ExportActionProvider {
	private static final Logger logger = Logger.getLogger(PefExportProviderImpl.class.getCanonicalName());
	private enum PefExportActionDescription {
		TO_TEXT(Messages.MENU_ITEM_EXPORT_TO_TEXT, ExportToText::new),
		SPLIT_PEF(Messages.MENU_ITEM_SPLIT_PEF, SplitPef::new);
		private final Supplier action;
		private final Messages resourceKey;
		private final String identifier;
		private PefExportActionDescription(Messages name, Supplier action) {
			this.action = action;
			this.resourceKey = name;
			this.identifier = String.format("%s.%s", this.getClass().getCanonicalName(), this.name());
		}

		ExportAction newAction() {
			return action.get();
		}
		
		String getIdentifier() {
			return identifier;
		}
		
		Messages getResourceKey() {
			return resourceKey;
		}

	}

	private static final ExecutorService EXE_SERVICE = Executors.newWorkStealingPool();
	
	private final Map actions;
	
	/**
	 * Creates a new instance.
	 */
	public PefExportProviderImpl() {
		this.actions = new LinkedHashMap<>();
		for (PefExportActionDescription d : PefExportActionDescription.values()) {
			actions.put(d.getIdentifier(), d);
		}
	}

	@Override
	public List listActions() {
		return actions.values().stream()
				.map(v->new ExportActionDescription.Builder(v.getIdentifier())
						.name(v.getResourceKey().localize())
						.build()
				)
				.collect(Collectors.toList());
	}

	@Override
	public boolean supportsFormat(FileDetails format) {
		return FileDetailsCatalog.PEF_FORMAT.getMediaType().equals(format.getMediaType());
	}

	@Override
	public boolean supportsAction(String id) {
		return actions.containsKey(id);
	}

	@Override
	public Optional newExportAction(String id) {
		return Optional.ofNullable(actions.get(id))
				.map(v->v.newAction());
	}
	
	private static class ExportToText implements ExportAction {

		@Override
		public void export(Window ownerWindow, File source) {
			FileChooser fileChooser = new FileChooser();
			fileChooser.setTitle(Messages.DIALOG_TITLE_EXPORT_TO_TEXT.localize());
			Settings.getSettings().getLastSavePath().ifPresent(v->fileChooser.setInitialDirectory(v));
			File target = fileChooser.showSaveDialog(ownerWindow);
			if (target!=null) {
				Settings.getSettings().setLastSavePath(target.getParentFile());
				// Use the preview table as the default
				Optional tableId = Optional.ofNullable(Settings.getSettings().getString(Keys.charset));
				// List available tables
				Collection fp = TableCatalog.newInstance().list();
				// Only display options if there is something to choose from
				if (fp.size()>1) {
					// Map tables to an adapter that can be displayed in a choice dialog
					List fpa = fp.stream()
							.map(v->new FactoryPropertiesAdapter(v))
							.sorted()
							.collect(Collectors.toList());
					// Make a final variable reference for lambda
					final Optional _tableId = tableId;
					// Find a default object in the list. If the selected table is in the list, choose that.
					// Otherwise, use the first item in the list.
					FactoryPropertiesAdapter selected = fpa.stream()
								.filter(v->_tableId.isPresent()&&v.getProperties().getIdentifier().equals(_tableId.get()))
								.findFirst()
								.orElse(fpa.get(0));
					ChoiceDialog dialog = new ChoiceDialog<>(selected, fpa);
					dialog.setTitle(Messages.DIALOG_TITLE_EXPORT_OPTIONS.localize());
					dialog.setHeaderText(Messages.MESSAGE_SELECT_BRAILLE_TABLE.localize());
					dialog.setContentText(Messages.LABEL_BRAILLE_TABLE.localize());
					tableId = dialog.showAndWait()
							.map(v->v.getProperties().getIdentifier());
				} else if (fp.size()==1) {
					// Nothing to choose from, just use the one item that's in the list.
					// At this point it doesn't matter if this isn't the same as the preferred table
					// above, because it either doesn't exist in the list and the export will fail,
					// or the preferred table is in fact the item in the list.
					tableId = Optional.of(fp.iterator().next().getIdentifier());
				}
				if (tableId.isPresent()) {
					final String _tableId = tableId.get();
					Task exportTask = new Task() {
						@Override
						protected Void call() throws Exception {
							PefExportActions.toText(source, target, _tableId);
							return null;
						}
					};
					exportTask.setOnSucceeded(e->{
						logger.info("Export completed.");
					});
					exportTask.setOnFailed(e->{
						exportTask.getException().printStackTrace();
						Alert alert = new Alert(AlertType.ERROR, exportTask.getException().toString(), ButtonType.OK);
						alert.showAndWait();
					});
					EXE_SERVICE.submit(exportTask);
				}
			}
		}
		
	}
	
	private static class SplitPef implements ExportAction {

		@Override
		public void export(Window ownerWindow, File source) {
			DirectoryChooser dirChooser = new DirectoryChooser();
			dirChooser.setTitle(Messages.DIALOG_TITLE_SPLIT_PEF.localize());
			Settings.getSettings().getLastSavePath().ifPresent(v->dirChooser.setInitialDirectory(v));
			File target = dirChooser.showDialog(ownerWindow);
			if (target!=null) {
				Settings.getSettings().setLastSavePath(target);
				if (target.listFiles().length>0) {
					Alert alert = new Alert(AlertType.CONFIRMATION, Messages.MESSAGE_CONFIRM_OVERWRITE.localize(), ButtonType.YES, ButtonType.NO, ButtonType.CANCEL);
					alert.setHeaderText(Messages.LABEL_FOLDER_NOT_EMPTY.localize());
					Optional ret = alert.showAndWait();
					if (ret.isPresent()) {
						ButtonType bt = ret.get();
						if (bt==ButtonType.CANCEL) {
							return;
						} else if (bt==ButtonType.NO) {
							export(ownerWindow, source);
							return;
						}
					}
				}
				Task exportTask = new Task() {
					@Override
					protected Void call() throws Exception {
						if (!PefExportActions.split(source, target)) {
							throw new RuntimeException("Failed to split");
						}
						return null;
					}
				};
				exportTask.setOnFailed(e->{
					exportTask.getException().printStackTrace();
					Alert alert = new Alert(AlertType.ERROR, exportTask.getException().toString(), ButtonType.OK);
					alert.showAndWait();
				});
				EXE_SERVICE.submit(exportTask);
			}
		}
		
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy