From c4bdde7eb5a3b527654b6a2a0de3743f5ba4cf7b Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 18 Mar 2018 12:01:33 +0100 Subject: [PATCH] JCR browser commands --- .../org/argeo/cms/e4/rap/CmsE4AdminApp.java | 18 +-- .../cms-admin.e4xmi | 22 +++- .../org/argeo/cms/e4/jcr/JcrBrowserView.java | 38 +++--- .../cms/e4/jcr/commands/AddFolderNode.java | 81 +++++++++++++ .../cms/e4/jcr/commands/DeleteNodes.java | 110 ++++++++++++++++++ .../argeo/cms/e4/jcr/commands/Refresh.java | 58 +++++++++ .../argeo/cms/e4/jcr/commands/RenameNode.java | 74 ++++++++++++ 7 files changed, 371 insertions(+), 30 deletions(-) rename {org.argeo.cms.e4.rap => org.argeo.cms.e4}/cms-admin.e4xmi (58%) create mode 100644 org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/AddFolderNode.java create mode 100644 org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/DeleteNodes.java create mode 100644 org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/Refresh.java create mode 100644 org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/RenameNode.java diff --git a/org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/CmsE4AdminApp.java b/org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/CmsE4AdminApp.java index 0a3e050cb..a8edd707b 100644 --- a/org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/CmsE4AdminApp.java +++ b/org.argeo.cms.e4.rap/src/org/argeo/cms/e4/rap/CmsE4AdminApp.java @@ -13,7 +13,6 @@ import org.eclipse.rap.rwt.application.Application.OperationMode; import org.eclipse.rap.rwt.application.ApplicationConfiguration; import org.eclipse.rap.rwt.application.EntryPoint; import org.eclipse.rap.rwt.client.WebClient; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; @@ -21,28 +20,21 @@ public class CmsE4AdminApp implements ApplicationConfiguration { private final BundleContext bc = FrameworkUtil.getBundle(CmsE4AdminApp.class).getBundleContext(); String pageTitle = "CMS Admin"; - String e4Xmi = "/cms-admin.e4xmi"; + String e4Xmi = "org.argeo.cms.e4/cms-admin.e4xmi"; String path = "/admin"; + String lifeCycleUri = "bundleclass://" + bc.getBundle().getSymbolicName() + "/" + CmsLoginLifecycle.class.getName(); public void configure(Application application) { Map properties = new HashMap(); properties.put(WebClient.PAGE_TITLE, pageTitle); - Bundle bundle = bc.getBundle(); - String e4XmiUri = bundle.getSymbolicName() + e4Xmi; - E4ApplicationConfig config = new E4ApplicationConfig(e4XmiUri, - "bundleclass://" + bundle.getSymbolicName() + "/" + CmsLoginLifecycle.class.getName(), null, false, - true, true); + E4ApplicationConfig config = new E4ApplicationConfig(e4Xmi, lifeCycleUri, null, false, true, true); config.isClearPersistedState(); E4EntryPointFactory entryPointFactory = new E4EntryPointFactory(config) { @Override public EntryPoint create() { Subject subject = new Subject(); - // return Subject.doAs(subject, new PrivilegedAction() { - // - // @Override - // public EntryPoint run() { EntryPoint ep = createEntryPoint(); EntryPoint authEp = new EntryPoint() { @@ -58,10 +50,6 @@ public class CmsE4AdminApp implements ApplicationConfiguration { }); } }; - // return authEp; - // } - // - // }); return authEp; } diff --git a/org.argeo.cms.e4.rap/cms-admin.e4xmi b/org.argeo.cms.e4/cms-admin.e4xmi similarity index 58% rename from org.argeo.cms.e4.rap/cms-admin.e4xmi rename to org.argeo.cms.e4/cms-admin.e4xmi index 58e6d6844..d4a86ae31 100644 --- a/org.argeo.cms.e4.rap/cms-admin.e4xmi +++ b/org.argeo.cms.e4/cms-admin.e4xmi @@ -7,7 +7,18 @@ - + + + + + + ViewMenu + + + + + + @@ -22,6 +33,14 @@ + + + + + + + + @@ -29,4 +48,5 @@ + diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java index 3eff80733..dd5bcb184 100644 --- a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java @@ -39,13 +39,15 @@ import org.argeo.cms.ui.jcr.NodeLabelProvider; import org.argeo.cms.ui.jcr.OsgiRepositoryRegister; import org.argeo.cms.ui.jcr.PropertiesContentProvider; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; +import org.argeo.cms.util.CmsUtils; import org.argeo.eclipse.ui.EclipseUiException; import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; import org.argeo.eclipse.ui.jcr.utils.NodeViewerComparer; import org.argeo.node.security.CryptoKeyring; -import org.eclipse.jface.action.MenuManager; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -58,16 +60,19 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Menu; /** * Basic View to display a sash form to browse a JCR compliant multiple * repository environment */ public class JcrBrowserView { + public final static String ID = "org.argeo.cms.e4.jcrbrowser"; + + @Inject + private ESelectionService selectionService; + private boolean sortChildNodes = true; /* DEPENDENCY INJECTION */ @@ -94,13 +99,13 @@ public class JcrBrowserView { parent.setLayout(new FillLayout()); SashForm sashForm = new SashForm(parent, SWT.VERTICAL); - sashForm.setSashWidth(4); - sashForm.setLayout(new FillLayout()); + // sashForm.setSashWidth(4); + // sashForm.setLayout(new FillLayout()); // Create the tree on top of the view Composite top = new Composite(sashForm, SWT.NONE); - GridLayout gl = new GridLayout(1, false); - top.setLayout(gl); + // GridLayout gl = new GridLayout(1, false); + top.setLayout(CmsUtils.noSpaceGridLayout()); try { this.userSession = this.nodeRepository.login(); @@ -115,21 +120,26 @@ public class JcrBrowserView { nodesViewer = createNodeViewer(top, nodeContentProvider); // context menu : it is completely defined in the plugin.xml file. - MenuManager menuManager = new MenuManager(); - Menu menu = menuManager.createContextMenu(nodesViewer.getTree()); + // MenuManager menuManager = new MenuManager(); + // Menu menu = menuManager.createContextMenu(nodesViewer.getTree()); - nodesViewer.getTree().setMenu(menu); + // nodesViewer.getTree().setMenu(menu); nodesViewer.setInput(""); // Create the property viewer on the bottom Composite bottom = new Composite(sashForm, SWT.NONE); - bottom.setLayout(new GridLayout(1, false)); + bottom.setLayout(CmsUtils.noSpaceGridLayout()); propertiesViewer = createPropertiesViewer(bottom); sashForm.setWeights(getWeights()); nodesViewer.setComparer(new NodeViewerComparer()); - + nodesViewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + selectionService.setSelection(selection.toList()); + } + }); // getSite().registerContextMenu(menuManager, nodesViewer); // getSite().setSelectionProvider(nodesViewer); } @@ -167,7 +177,7 @@ public class JcrBrowserView { tmpNodeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); tmpNodeViewer.setContentProvider(nodeContentProvider); - tmpNodeViewer.setLabelProvider(new NodeLabelProvider()); + tmpNodeViewer.setLabelProvider((IBaseLabelProvider) new NodeLabelProvider()); tmpNodeViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { if (!event.getSelection().isEmpty()) { @@ -196,7 +206,7 @@ public class JcrBrowserView { } protected TableViewer createPropertiesViewer(Composite parent) { - propertiesViewer = new TableViewer(parent); + propertiesViewer = new TableViewer(parent, SWT.NONE); propertiesViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); propertiesViewer.getTable().setHeaderVisible(true); propertiesViewer.setContentProvider(new PropertiesContentProvider()); diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/AddFolderNode.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/AddFolderNode.java new file mode 100644 index 000000000..7c97817c0 --- /dev/null +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/AddFolderNode.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.cms.e4.jcr.commands; + +import java.util.List; + +import javax.inject.Named; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.cms.e4.jcr.JcrBrowserView; +import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; +import org.argeo.cms.ui.jcr.model.WorkspaceElem; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.eclipse.ui.dialogs.ErrorFeedback; +import org.argeo.eclipse.ui.dialogs.SingleValue; +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.services.IServiceConstants; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; + +/** + * Adds a node of type nt:folder, only on {@link SingleJcrNodeElem} and + * {@link WorkspaceElem} TreeObject types. + * + * This handler assumes that a selection provider is available and picks only + * first selected item. It is UI's job to enable the command only when the + * selection contains one and only one element. Thus no parameter is passed + * through the command. + */ +public class AddFolderNode { + @Execute + public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { + List selection = (List) selectionService.getSelection(); + JcrBrowserView view = (JcrBrowserView) part.getObject(); + + if (selection != null && selection.size() == 1) { + TreeParent treeParentNode = null; + Node jcrParentNode = null; + Object obj = selection.get(0); + + if (obj instanceof SingleJcrNodeElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((SingleJcrNodeElem) treeParentNode).getNode(); + } else if (obj instanceof WorkspaceElem) { + treeParentNode = (TreeParent) obj; + jcrParentNode = ((WorkspaceElem) treeParentNode).getRootNode(); + } else + return; + + String folderName = SingleValue.ask("Folder name", "Enter folder name"); + if (folderName != null) { + try { + jcrParentNode.addNode(folderName, NodeType.NT_FOLDER); + jcrParentNode.getSession().save(); + view.nodeAdded(treeParentNode); + } catch (RepositoryException e) { + ErrorFeedback.show("Cannot create folder " + folderName + " under " + treeParentNode, e); + } + } + } else { + // ErrorFeedback.show(WorkbenchUiPlugin + // .getMessage("errorUnvalidNtFolderNodeType")); + ErrorFeedback.show("Invalid NT folder node type"); + } + } +} diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/DeleteNodes.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/DeleteNodes.java new file mode 100644 index 000000000..16813627d --- /dev/null +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/DeleteNodes.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.cms.e4.jcr.commands; + +import java.util.List; + +import javax.inject.Named; +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.e4.jcr.JcrBrowserView; +import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; +import org.argeo.cms.ui.jcr.model.WorkspaceElem; +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.eclipse.ui.dialogs.ErrorFeedback; +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.services.IServiceConstants; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Display; + +/** + * Delete the selected nodes: both in the JCR repository and in the UI view. + * Warning no check is done, except implementation dependent native checks, + * handle with care. + * + * This handler is still 'hard linked' to a GenericJcrBrowser view to enable + * correct tree refresh when a node is added. This must be corrected in future + * versions. + */ +public class DeleteNodes { + @Execute + public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, ESelectionService selectionService) { + List selection = (List) selectionService.getSelection(); + if (selection == null) + return; + + JcrBrowserView view = (JcrBrowserView) part.getObject(); + + // confirmation + StringBuffer buf = new StringBuffer(""); + for (Object o : selection) { + SingleJcrNodeElem sjn = (SingleJcrNodeElem) o; + buf.append(sjn.getName()).append(' '); + } + Boolean doRemove = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(), "Confirm deletion", + "Do you want to delete " + buf + "?"); + + // operation + if (doRemove) { + SingleJcrNodeElem ancestor = null; + WorkspaceElem rootAncestor = null; + try { + for (Object obj : selection) { + if (obj instanceof SingleJcrNodeElem) { + // Cache objects + SingleJcrNodeElem sjn = (SingleJcrNodeElem) obj; + TreeParent tp = (TreeParent) sjn.getParent(); + Node node = sjn.getNode(); + + // Jcr Remove + node.remove(); + node.getSession().save(); + // UI remove + tp.removeChild(sjn); + + // Check if the parent is the root node + if (tp instanceof WorkspaceElem) + rootAncestor = (WorkspaceElem) tp; + else + ancestor = getOlder(ancestor, (SingleJcrNodeElem) tp); + } + } + if (rootAncestor != null) + view.nodeRemoved(rootAncestor); + else if (ancestor != null) + view.nodeRemoved(ancestor); + } catch (Exception e) { + ErrorFeedback.show("Cannot delete selected node ", e); + } + } + } + + private SingleJcrNodeElem getOlder(SingleJcrNodeElem A, SingleJcrNodeElem B) { + try { + if (A == null) + return B == null ? null : B; + // Todo enhanced this method + else + return A.getNode().getDepth() <= B.getNode().getDepth() ? A : B; + } catch (RepositoryException re) { + throw new EclipseUiException("Cannot find ancestor", re); + } + } +} diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/Refresh.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/Refresh.java new file mode 100644 index 000000000..dea514318 --- /dev/null +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/Refresh.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.cms.e4.jcr.commands; + +import java.util.List; + +import javax.inject.Named; + +import org.argeo.cms.e4.jcr.JcrBrowserView; +import org.argeo.cms.ui.jcr.JcrBrowserUtils; +import org.argeo.eclipse.ui.TreeParent; +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.services.IServiceConstants; +import org.eclipse.e4.ui.workbench.modeling.EPartService; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; + +/** + * Force the selected objects of the active view to be refreshed doing the + * following: + *
    + *
  1. The model objects are recomputed
  2. + *
  3. the view is refreshed
  4. + *
+ */ +public class Refresh { + + @Execute + public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, EPartService partService, + ESelectionService selectionService) { + + JcrBrowserView view = (JcrBrowserView) part.getObject(); + List selection = (List) selectionService.getSelection(); + + if (selection != null && !selection.isEmpty()) { + for (Object obj : selection) + if (obj instanceof TreeParent) { + TreeParent tp = (TreeParent) obj; + JcrBrowserUtils.forceRefreshIfNeeded(tp); + view.refresh(obj); + } + } else if (view instanceof JcrBrowserView) + view.refresh(null); // force full refresh + } +} diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/RenameNode.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/RenameNode.java new file mode 100644 index 000000000..48e1b931a --- /dev/null +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/commands/RenameNode.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.cms.e4.jcr.commands; + +import java.util.List; + +import javax.inject.Named; +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.cms.e4.jcr.JcrBrowserView; +import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; +import org.argeo.eclipse.ui.EclipseUiException; +import org.argeo.eclipse.ui.dialogs.SingleValue; +import org.argeo.jcr.JcrUtils; +import org.eclipse.e4.core.di.annotations.Execute; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.services.IServiceConstants; +import org.eclipse.e4.ui.workbench.modeling.EPartService; +import org.eclipse.e4.ui.workbench.modeling.ESelectionService; + +/** + * Canonically call JCR Session#move(String, String) on the first element + * returned by HandlerUtil#getActiveWorkbenchWindow() + * (...getActivePage().getSelection()), if it is a {@link SingleJcrNodeElem}. + * The user must then fill a new name in and confirm + */ +public class RenameNode { + @Execute + public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart part, EPartService partService, + ESelectionService selectionService) { + List selection = (List) selectionService.getSelection(); + if (selection == null || selection.size() != 1) + return; + JcrBrowserView view = (JcrBrowserView) part.getObject(); + + Object element = selection.get(0); + if (element instanceof SingleJcrNodeElem) { + SingleJcrNodeElem sjn = (SingleJcrNodeElem) element; + Node node = sjn.getNode(); + Session session = null; + String newName = null; + String oldPath = null; + try { + newName = SingleValue.ask("New node name", "Please provide a new name for [" + node.getName() + "]"); + // TODO sanity check and user feedback + newName = JcrUtils.replaceInvalidChars(newName); + oldPath = node.getPath(); + session = node.getSession(); + session.move(oldPath, JcrUtils.parentPath(oldPath) + "/" + newName); + session.save(); + + // Manually refresh the browser view. Must be enhanced + view.refresh(sjn); + } catch (RepositoryException e) { + throw new EclipseUiException("Unable to rename " + node + " to " + newName, e); + } + } + } +} -- 2.30.2