X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=library%2Forg.argeo.library.ui%2Fsrc%2Forg%2Fargeo%2Flibrary%2Fui%2FDocumentsUiService.java;fp=library%2Forg.argeo.library.ui%2Fsrc%2Forg%2Fargeo%2Flibrary%2Fui%2FDocumentsUiService.java;h=ad13d28863130992148881fa7174afae7a261008;hp=0000000000000000000000000000000000000000;hb=e8d31e8321bb18489b37a53a32db833f8efb5ddf;hpb=44b2a06f610d0a13947af46f0f27e7d814865972 diff --git a/library/org.argeo.library.ui/src/org/argeo/library/ui/DocumentsUiService.java b/library/org.argeo.library.ui/src/org/argeo/library/ui/DocumentsUiService.java new file mode 100644 index 0000000..ad13d28 --- /dev/null +++ b/library/org.argeo.library.ui/src/org/argeo/library/ui/DocumentsUiService.java @@ -0,0 +1,310 @@ +package org.argeo.library.ui; + +import static org.argeo.cms.ui.dialogs.CmsMessageDialog.openConfirm; +import static org.argeo.cms.ui.dialogs.CmsMessageDialog.openError; +import static org.argeo.cms.ui.dialogs.SingleValueDialog.ask; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.net.URI; +import java.nio.file.DirectoryNotEmptyException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.cms.ui.dialogs.CmsFeedback; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.eclipse.ui.specific.OpenFile; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; + +public class DocumentsUiService { + private final static Log log = LogFactory.getLog(DocumentsUiService.class); + + // Default known actions + public final static String ACTION_ID_CREATE_FOLDER = "createFolder"; + public final static String ACTION_ID_BOOKMARK_FOLDER = "bookmarkFolder"; + public final static String ACTION_ID_SHARE_FOLDER = "shareFolder"; + public final static String ACTION_ID_DOWNLOAD_FOLDER = "downloadFolder"; + public final static String ACTION_ID_RENAME = "rename"; + public final static String ACTION_ID_DELETE = "delete"; + public final static String ACTION_ID_UPLOAD_FILE = "uploadFiles"; + // public final static String ACTION_ID_OPEN = "open"; + public final static String ACTION_ID_DELETE_BOOKMARK = "deleteBookmark"; + public final static String ACTION_ID_RENAME_BOOKMARK = "renameBookmark"; + + public String getLabel(String actionId) { + switch (actionId) { + case ACTION_ID_CREATE_FOLDER: + return "Create Folder"; + case ACTION_ID_BOOKMARK_FOLDER: + return "Bookmark Folder"; + case ACTION_ID_SHARE_FOLDER: + return "Share Folder"; + case ACTION_ID_DOWNLOAD_FOLDER: + return "Download as zip archive"; + case ACTION_ID_RENAME: + return "Rename"; + case ACTION_ID_DELETE: + return "Delete"; + case ACTION_ID_UPLOAD_FILE: + return "Upload Files"; +// case ACTION_ID_OPEN: +// return "Open"; + case ACTION_ID_DELETE_BOOKMARK: + return "Delete bookmark"; + case ACTION_ID_RENAME_BOOKMARK: + return "Rename bookmark"; + default: + throw new IllegalArgumentException("Unknown action ID " + actionId); + } + } + + public void openFile(Path toOpenPath) { + try { + String name = toOpenPath.getFileName().toString(); + File tmpFile = File.createTempFile("tmp", name); + tmpFile.deleteOnExit(); + try (OutputStream os = new FileOutputStream(tmpFile)) { + Files.copy(toOpenPath, os); + } catch (IOException e) { + throw new IllegalStateException("Cannot open copy " + name + " to tmpFile.", e); + } + String uri = Paths.get(tmpFile.getAbsolutePath()).toUri().toString(); + Map params = new HashMap(); + params.put(OpenFile.PARAM_FILE_NAME, name); + params.put(OpenFile.PARAM_FILE_URI, uri); + // FIXME open file without a command + // CommandUtils.callCommand(OpenFile.ID, params); + } catch (IOException e1) { + throw new IllegalStateException("Cannot create tmp copy of " + toOpenPath, e1); + } + } + + public boolean deleteItems(Shell shell, IStructuredSelection selection) { + if (selection.isEmpty()) + return false; + + StringBuilder builder = new StringBuilder(); + @SuppressWarnings("unchecked") + Iterator iterator = selection.iterator(); + List paths = new ArrayList<>(); + + while (iterator.hasNext()) { + Path path = (Path) iterator.next(); + builder.append(path.getFileName() + ", "); + paths.add(path); + } + String msg = "You are about to delete following elements: " + builder.substring(0, builder.length() - 2) + + ". Are you sure?"; + if (openConfirm(msg)) { + for (Path path : paths) { + try { + // recursively delete directory and its content + Files.walkFileTree(path, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (DirectoryNotEmptyException e) { + String errMsg = path.getFileName() + " cannot be deleted: directory is not empty."; + openError( errMsg); + throw new IllegalArgumentException("Cannot delete path " + path, e); + } catch (IOException e) { + String errMsg = e.toString(); + openError(errMsg); + throw new IllegalArgumentException("Cannot delete path " + path, e); + } + } + return true; + } + return false; + } + + public boolean renameItem(Shell shell, Path parentFolderPath, Path toRenamePath) { + String msg = "Enter a new name:"; + String name = ask( msg, toRenamePath.getFileName().toString()); + // TODO enhance check of name validity + if (EclipseUiUtils.notEmpty(name)) { + try { + Path child = parentFolderPath.resolve(name); + if (Files.exists(child)) { + String errMsg = "An object named " + name + " already exists at " + parentFolderPath.toString() + + ", please provide another name"; + openError( errMsg); + throw new IllegalArgumentException(errMsg); + } else { + Files.move(toRenamePath, child); + return true; + } + } catch (IOException e) { + throw new IllegalStateException("Cannot rename " + name + " at " + parentFolderPath.toString(), e); + } + } + return false; + } + + public boolean createFolder(Shell shell, Path currFolderPath) { + String msg = "Enter a name:"; + String name = ask( msg); + // TODO enhance check of name validity + if (EclipseUiUtils.notEmpty(name)) { + name = name.trim(); + try { + Path child = currFolderPath.resolve(name); + if (Files.exists(child)) { + String errMsg = "A folder named " + name + " already exists at " + currFolderPath.toString() + + ", cannot create"; + openError(errMsg); + throw new IllegalArgumentException(errMsg); + } else { + Files.createDirectories(child); + return true; + } + } catch (IOException e) { + throw new IllegalStateException("Cannot create folder " + name + " at " + currFolderPath.toString(), e); + } + } + return false; + } + +// public void bookmarkFolder(Path toBookmarkPath, Repository repository, DocumentsService documentsService) { +// String msg = "Provide a name:"; +// String name = SingleQuestion.ask("Create bookmark", msg, toBookmarkPath.getFileName().toString()); +// if (EclipseUiUtils.notEmpty(name)) +// documentsService.createFolderBookmark(toBookmarkPath, name, repository); +// } + + public boolean uploadFiles(Shell shell, Path currFolderPath) { +// shell = Display.getCurrent().getActiveShell();// ignore argument + try { + FileDialog dialog = new FileDialog(shell, SWT.MULTI); + dialog.setText("Choose one or more files to upload"); + + if (EclipseUiUtils.notEmpty(dialog.open())) { + String[] names = dialog.getFileNames(); + // Workaround small differences between RAP and RCP + // 1. returned names are absolute path on RAP and + // relative in RCP + // 2. in RCP we must use getFilterPath that does not + // exists on RAP + Method filterMethod = null; + Path parPath = null; + try { + filterMethod = dialog.getClass().getDeclaredMethod("getFilterPath"); + String filterPath = (String) filterMethod.invoke(dialog); + parPath = Paths.get(filterPath); + } catch (NoSuchMethodException nsme) { // RAP + } + if (names.length == 0) + return false; + else { + loop: for (String name : names) { + Path tmpPath = Paths.get(name); + if (parPath != null) + tmpPath = parPath.resolve(tmpPath); + if (Files.exists(tmpPath)) { + URI uri = tmpPath.toUri(); + String uriStr = uri.toString(); + + if (Files.isDirectory(tmpPath)) { + openError( + "Upload of directories in the system is not yet implemented"); + continue loop; + } + Path targetPath = currFolderPath.resolve(tmpPath.getFileName().toString()); + try (InputStream in = new FileInputStream(tmpPath.toFile())) { + Files.copy(in, targetPath); + Files.delete(tmpPath); + } + if (log.isDebugEnabled()) + log.debug("copied uploaded file " + uriStr + " to " + targetPath.toString()); + } else { + String msg = "Cannot copy tmp file from " + tmpPath.toString(); + if (parPath != null) + msg += "\nPlease remember that file upload fails when choosing files from the \"Recently Used\" bookmarks on some OS"; + openError( msg); + continue loop; + } + } + return true; + } + } + } catch (Exception e) { + CmsFeedback.show("Cannot import files to " + currFolderPath,e); + } + return false; + } + +// public boolean deleteBookmark(Shell shell, IStructuredSelection selection, Node bookmarkParent) { +// if (selection.isEmpty()) +// return false; +// +// StringBuilder builder = new StringBuilder(); +// @SuppressWarnings("unchecked") +// Iterator iterator = selection.iterator(); +// List nodes = new ArrayList<>(); +// +// while (iterator.hasNext()) { +// Node node = (Node) iterator.next(); +// builder.append(Jcr.get(node, Property.JCR_TITLE) + ", "); +// nodes.add(node); +// } +// String msg = "You are about to delete following bookmark: " + builder.substring(0, builder.length() - 2) +// + ". Are you sure?"; +// if (MessageDialog.openConfirm(shell, "Confirm deletion", msg)) { +// Session session = Jcr.session(bookmarkParent); +// try { +// if (session.hasPendingChanges()) +// throw new DocumentsException("Cannot remove bookmarks, session is not clean"); +// for (Node path : nodes) +// path.remove(); +// bookmarkParent.getSession().save(); +// return true; +// } catch (RepositoryException e) { +// JcrUtils.discardQuietly(session); +// throw new DocumentsException("Cannot delete bookmarks " + builder.toString(), e); +// } +// } +// return false; +// } + +// public boolean renameBookmark(IStructuredSelection selection) { +// if (selection.isEmpty() || selection.size() > 1) +// return false; +// Node toRename = (Node) selection.getFirstElement(); +// String msg = "Please provide a new name."; +// String name = SingleQuestion.ask("Rename bookmark", msg, ConnectJcrUtils.get(toRename, Property.JCR_TITLE)); +// if (EclipseUiUtils.notEmpty(name) +// && ConnectJcrUtils.setJcrProperty(toRename, Property.JCR_TITLE, PropertyType.STRING, name)) { +// ConnectJcrUtils.saveIfNecessary(toRename); +// return true; +// } +// return false; +// } +}