Add a few functionalities to dist UI
authorBruno Sinou <bsinou@argeo.org>
Thu, 21 Jun 2012 16:23:34 +0000 (16:23 +0000)
committerBruno Sinou <bsinou@argeo.org>
Thu, 21 Jun 2012 16:23:34 +0000 (16:23 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@5341 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/MANIFEST.MF
eclipse/plugins/org.argeo.slc.client.ui.dist/META-INF/spring/commands.xml
eclipse/plugins/org.argeo.slc.client.ui.dist/icons/addItem.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/icons/changeRights.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/icons/removeItem.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/plugin.xml
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CopyWorkspace.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CreateWorkspace.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/DeleteWorkspace.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/ManageWorkspaceAuth.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/RefreshDistributionsView.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/editors/DistributionEditor.java
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/editors/DistributionOverviewPage.java
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/CommandHelpers.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/NodeViewerComparator.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/views/DistributionsView.java
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChangeRightsWizard.java [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChooseRightsPage.java [new file with mode: 0644]

index 9d3d163af72d2e3d88b71914d571e34f0dfe3985..ed401485b7b5f23af0936eb0f8623d54e6e215a3 100644 (file)
@@ -15,6 +15,7 @@ Import-Package: aQute.lib.osgi;resolution:=optional,
  javax.jcr.nodetype;version="2.0.0",
  javax.jcr.query,
  javax.jcr.query.qom;version="2.0.0",
+ javax.jcr.security,
  org.apache.commons.io;version="1.4.0",
  org.apache.commons.logging;version="1.1.1",
  org.argeo,
index 00bf6111ea7e4e0e9cdff5787a401a8c60595b91..61f60e2a2910a1516c09ea701c3ca6144ddd639b 100644 (file)
                <property name="repository" ref="javaRepository" />
                <property name="workspace" value="argeo-tp-1-staging" />
        </bean>
+       <bean id="createWorkspace"
+               class="org.argeo.slc.client.ui.dist.commands.CreateWorkspace"
+               scope="prototype">
+               <property name="repository" ref="javaRepository" />
+       </bean>
+       <bean id="copyWorkspace"
+               class="org.argeo.slc.client.ui.dist.commands.CopyWorkspace"
+               scope="prototype">
+               <property name="repository" ref="javaRepository" />
+       </bean>
+       <bean id="deleteWorkspace"
+               class="org.argeo.slc.client.ui.dist.commands.DeleteWorkspace"
+               scope="prototype">
+               <property name="repository" ref="javaRepository" />
+       </bean>
+       <bean id="manageWorkspaceAuth"
+               class="org.argeo.slc.client.ui.dist.commands.ManageWorkspaceAuth"
+               scope="prototype">
+               <property name="repository" ref="javaRepository" />
+       </bean>
+       <bean id="refreshDistributionsView"
+               class="org.argeo.slc.client.ui.dist.commands.RefreshDistributionsView"
+               scope="prototype">
+       </bean>
 </beans>
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/addItem.gif b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/addItem.gif
new file mode 100644 (file)
index 0000000..a5ac28d
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/addItem.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/changeRights.gif b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/changeRights.gif
new file mode 100644 (file)
index 0000000..a6b251f
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/changeRights.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/removeItem.gif b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/removeItem.gif
new file mode 100644 (file)
index 0000000..2b88506
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui.dist/icons/removeItem.gif differ
index 003c8f92f36ad4b1a91ab5ea1de4bcdc3c3e3e63..3b426c6b380283398d06e36031e296dc719faecc 100644 (file)
             id="org.argeo.slc.client.ui.dist.normalizeDistribution"
             defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
             name="Normalize Distribution">
+       </command>
+       
+               <!-- TO MANIPULATE WORKSPACES -->
+               <command
+            id="org.argeo.slc.client.ui.dist.createWorkspace"
+            defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+            name="Create Workspace">
+       </command>
+       <command
+            id="org.argeo.slc.client.ui.dist.deleteWorkspace"
+            defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+            name="Delete chosen Workspace">
+            <commandParameter
+                       id="org.argeo.slc.client.ui.dist.workspaceName"
+                       name="Workspace Name">
+                       </commandParameter>
+       </command>
+       <command
+            id="org.argeo.slc.client.ui.dist.copyWorkspace"
+            defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+            name="Copy chosen Workspace">
+            <commandParameter
+                       id="org.argeo.slc.client.ui.dist.workspaceName"
+                       name="Workspace Name">
+                       </commandParameter>
+       </command>
+       <command
+            id="org.argeo.slc.client.ui.dist.manageWorkspaceAuth"
+            defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+            name="Manage workspace authorizations">
+            <commandParameter
+                       id="org.argeo.slc.client.ui.dist.workspaceName"
+                       name="Workspace Name">
+                       </commandParameter>
+       </command>
+       <command
+            id="org.argeo.slc.client.ui.dist.refreshDistributionsView"
+            defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
+            name="Refresh Distributions View">
        </command>
     </extension>
        <extension
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CopyWorkspace.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CopyWorkspace.java
new file mode 100644 (file)
index 0000000..5e011d1
--- /dev/null
@@ -0,0 +1,158 @@
+package org.argeo.slc.client.ui.dist.commands;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+/**
+ * Create a copy of the chosen workspace in the current repository.
+ */
+
+public class CopyWorkspace extends AbstractHandler {
+       private static final Log log = LogFactory.getLog(CopyWorkspace.class);
+       public final static String ID = DistPlugin.ID + ".copyWorkspace";
+       public final static String PARAM_WORKSPACE_NAME = DistPlugin.ID
+                       + ".workspaceName";
+       public final static String DEFAULT_LABEL = "Copy this workspace";
+       public final static String DEFAULT_ICON_PATH = "icons/addItem.gif";
+
+       /* DEPENDENCY INJECTION */
+       private Repository repository;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               String srcWorkspaceName = event.getParameter(PARAM_WORKSPACE_NAME);
+
+               if (log.isTraceEnabled())
+                       log.debug("WORKSPACE " + srcWorkspaceName + " About to be copied");
+
+               MessageDialog.openWarning(DistPlugin.getDefault()
+                               .getWorkbench().getDisplay().getActiveShell(),
+                               "WARNING", "Not yet implemented");
+               return null;
+               //
+               //
+               // IWorkbenchWindow iww = DistPlugin.getDefault().getWorkbench()
+               // .getActiveWorkbenchWindow();
+               // InputDialog inputDialog = new InputDialog(iww.getShell(),
+               // "New copy of the current workspace",
+               // "Choose a name for the workspace to create", "", null);
+               // inputDialog.open();
+               // String newWorkspaceName = inputDialog.getValue();
+               // Session srcSession = null;
+               // Session newSession = null;
+               // try {
+               // srcSession = repository.login(srcWorkspaceName);
+               // // FIXME: simple call to Workspace.create(newName, oldName) does not
+               // // work
+               //
+               // srcSession.getWorkspace().createWorkspace(newWorkspaceName,
+               // srcWorkspaceName);
+               //
+               // // // Create the workspace
+               // // srcSession.getWorkspace().createWorkspace(newWorkspaceName);
+               // // Node srcRootNode = srcSession.getRootNode();
+               // // // log in the newly created workspace
+               // // newSession = repository.login(newWorkspaceName);
+               // // newSession.save();
+               // // Node newRootNode = newSession.getRootNode();
+               // // copy(srcRootNode, newRootNode);
+               // // newSession.save();
+               //
+               // CommandHelpers.callCommand(RefreshDistributionsView.ID);
+               // } catch (RepositoryException re) {
+               // throw new ArgeoException(
+               // "Unexpected error while creating the new workspace.", re);
+               // } finally {
+               // if (srcSession != null)
+               // srcSession.logout();
+               // if (newSession != null)
+               // newSession.logout();
+               // }
+               // return null;
+       }
+
+       // FIXME : commons is frozen, cannot fix the problem directly there.
+       // test and report corresponding patch
+       private void copy(Node fromNode, Node toNode) {
+
+               try {
+                       // cannot manipulate security nodes this way:
+                       if (fromNode.isNodeType("rep:ACL"))
+                               return;
+                       // process properties
+                       PropertyIterator pit = fromNode.getProperties();
+                       properties: while (pit.hasNext()) {
+                               Property fromProperty = pit.nextProperty();
+                               String propertyName = fromProperty.getName();
+                               if (toNode.hasProperty(propertyName)
+                                               && toNode.getProperty(propertyName).getDefinition()
+                                                               .isProtected())
+                                       continue properties;
+
+                               if (fromProperty.getDefinition().isProtected())
+                                       continue properties;
+
+                               if (propertyName.equals("jcr:created")
+                                               || propertyName.equals("jcr:createdBy")
+                                               || propertyName.equals("jcr:lastModified")
+                                               || propertyName.equals("jcr:lastModifiedBy"))
+                                       continue properties;
+
+                               if (fromProperty.isMultiple()) {
+                                       toNode.setProperty(propertyName, fromProperty.getValues());
+                               } else {
+                                       toNode.setProperty(propertyName, fromProperty.getValue());
+                               }
+                       }
+
+                       // update jcr:lastModified and jcr:lastModifiedBy in toNode in case
+                       // they existed, before adding the mixins
+                       if (!toNode.getDefinition().isProtected())
+                               JcrUtils.updateLastModified(toNode);
+
+                       // add mixins
+                       for (NodeType mixinType : fromNode.getMixinNodeTypes()) {
+                               toNode.addMixin(mixinType.getName());
+                       }
+
+                       // process children nodes
+                       NodeIterator nit = fromNode.getNodes();
+                       while (nit.hasNext()) {
+                               Node fromChild = nit.nextNode();
+                               Integer index = fromChild.getIndex();
+                               String nodeRelPath = fromChild.getName() + "[" + index + "]";
+                               Node toChild;
+                               if (toNode.hasNode(nodeRelPath))
+                                       toChild = toNode.getNode(nodeRelPath);
+                               else
+                                       toChild = toNode.addNode(fromChild.getName(), fromChild
+                                                       .getPrimaryNodeType().getName());
+                               copy(fromChild, toChild);
+                       }
+
+                       toNode.getSession().save();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot copy " + fromNode + " to "
+                                       + toNode, e);
+               }
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CreateWorkspace.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/CreateWorkspace.java
new file mode 100644 (file)
index 0000000..a0b0b51
--- /dev/null
@@ -0,0 +1,57 @@
+package org.argeo.slc.client.ui.dist.commands;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+
+/**
+ * Create a new empty workspace in the current repository.
+ */
+
+public class CreateWorkspace extends AbstractHandler {
+       private static final Log log = LogFactory.getLog(CreateWorkspace.class);
+       public final static String ID = DistPlugin.ID + ".createWorkspace";
+       public final static String DEFAULT_LABEL = "Create new workspace";
+       public final static String DEFAULT_ICON_PATH = "icons/addItem.gif";
+
+       /* DEPENDENCY INJECTION */
+       private Repository repository;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               IWorkbenchWindow iww = DistPlugin.getDefault().getWorkbench()
+                               .getActiveWorkbenchWindow();
+               // TODO : add an input validator
+               InputDialog inputDialog = new InputDialog(iww.getShell(),
+                               "New workspace", "Choose a name for the workspace to create",
+                               "", null);
+               inputDialog.open();
+               String workspaceName = inputDialog.getValue();
+               try {
+                       Session session = repository.login();
+                       session.getWorkspace().createWorkspace(workspaceName);
+                       CommandHelpers.callCommand(RefreshDistributionsView.ID);
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while creating the new workspace.", re);
+               }
+               if (log.isTraceEnabled())
+                       log.debug("WORKSPACE " + workspaceName + " CREATED");
+               return null;
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/DeleteWorkspace.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/DeleteWorkspace.java
new file mode 100644 (file)
index 0000000..a0e940d
--- /dev/null
@@ -0,0 +1,65 @@
+package org.argeo.slc.client.ui.dist.commands;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.dialogs.MessageDialog;
+
+/**
+ * Delete chosen workspace in the current repository.
+ */
+
+public class DeleteWorkspace extends AbstractHandler {
+       // private static final Log log = LogFactory.getLog(DeleteWorkspace.class);
+       public final static String ID = DistPlugin.ID + ".deleteWorkspace";
+       public final static String PARAM_WORKSPACE_NAME = DistPlugin.ID
+                       + ".workspaceName";
+       public final static String DEFAULT_LABEL = "Delete current workspace";
+       public final static String DEFAULT_ICON_PATH = "icons/removeItem.gif";
+
+       /* DEPENDENCY INJECTION */
+       private Repository repository;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               String workspaceName = event.getParameter(PARAM_WORKSPACE_NAME);
+               String msg = "Your are about to definitively delete this workspace ["
+                               + workspaceName + "].\n Do you really want to proceed ?";
+
+               MessageDialog.openWarning(DistPlugin.getDefault()
+                               .getWorkbench().getDisplay().getActiveShell(),
+                               "WARNING", "Not yet implemented");
+               return null;
+               
+//             boolean result = MessageDialog.openConfirm(DistPlugin.getDefault()
+//                             .getWorkbench().getDisplay().getActiveShell(),
+//                             "Confirm deletion", msg);
+//             if (result) {
+//                     Session session = null;
+//                     try {
+//                             session = repository.login();
+//                             session.getWorkspace().deleteWorkspace(workspaceName);
+//                             CommandHelpers.callCommand(RefreshDistributionsView.ID);
+//                     } catch (RepositoryException re) {
+//                             throw new ArgeoException(
+//                                             "Unexpected error while deleting workspace ["
+//                                                             + workspaceName + "].", re);
+//                     } finally {
+//                             if (session != null)
+//                                     session.logout();
+//                     }
+//             }
+//             return null;
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/ManageWorkspaceAuth.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/ManageWorkspaceAuth.java
new file mode 100644 (file)
index 0000000..09ece2f
--- /dev/null
@@ -0,0 +1,57 @@
+package org.argeo.slc.client.ui.dist.commands;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+
+import org.argeo.ArgeoException;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.wizards.ChangeRightsWizard;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Open a dialog to change rights on the root node of the current workspace.
+ */
+
+public class ManageWorkspaceAuth extends AbstractHandler {
+       // private static final Log log =
+       // LogFactory.getLog(ManageWorkspaceAuth.class);
+       public final static String ID = DistPlugin.ID + ".manageWorkspaceAuth";
+       public final static String PARAM_WORKSPACE_NAME = DistPlugin.ID
+                       + ".workspaceName";
+       public final static String DEFAULT_LABEL = "Change rights for current workspace";
+       public final static String DEFAULT_ICON_PATH = "icons/changeRights.gif";
+
+       /* DEPENDENCY INJECTION */
+       private Repository repository;
+
+       private Session session;
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               String workspaceName = event.getParameter(PARAM_WORKSPACE_NAME);
+               try {
+                       session = repository.login(workspaceName);
+                       ChangeRightsWizard wizard = new ChangeRightsWizard(session);
+                       WizardDialog dialog = new WizardDialog(
+                                       HandlerUtil.getActiveShell(event), wizard);
+                       dialog.open();
+                       return null;
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while creating the new workspace.", re);
+               } finally {
+                       if (session != null)
+                               session.logout();
+               }
+       }
+
+       /* DEPENDENCY INJECTION */
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/RefreshDistributionsView.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/commands/RefreshDistributionsView.java
new file mode 100644 (file)
index 0000000..a9ba0a9
--- /dev/null
@@ -0,0 +1,28 @@
+package org.argeo.slc.client.ui.dist.commands;
+
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.views.DistributionsView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Force refresh of the DistributionsView
+ */
+
+public class RefreshDistributionsView extends AbstractHandler {
+       // private static final Log log = LogFactory
+       // .getLog(RefreshDistributionsView.class);
+       public final static String ID = DistPlugin.ID + ".refreshDistributionsView";
+       public final static String DEFAULT_LABEL = "Refresh the distribution view";
+       public final static String DEFAULT_ICON_PATH = "icons/refresh.png";
+
+       public Object execute(ExecutionEvent event) throws ExecutionException {
+               IWorkbenchPart activePart = DistPlugin.getDefault().getWorkbench()
+                               .getActiveWorkbenchWindow().getActivePage().getActivePart();
+               if (activePart instanceof DistributionsView)
+                       ((DistributionsView) activePart).refresh();
+               return null;
+       }
+}
index 7a274480bd927d2ff17b10d304521543baf2ae12..6c6756c8950cc62128808242b5db0dbb37b60478 100644 (file)
  */
 package org.argeo.slc.client.ui.dist.editors;
 
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
-import javax.jcr.query.QueryManager;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.qom.Ordering;
-import javax.jcr.query.qom.QueryObjectModel;
-import javax.jcr.query.qom.QueryObjectModelFactory;
-import javax.jcr.query.qom.Selector;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.ErrorFeedback;
-import org.argeo.jcr.JcrUtils;
 import org.argeo.slc.client.ui.dist.DistPlugin;
 import org.argeo.slc.jcr.SlcNames;
-import org.argeo.slc.jcr.SlcTypes;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Table;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.forms.IManagedForm;
 import org.eclipse.ui.forms.editor.FormEditor;
-import org.eclipse.ui.forms.editor.FormPage;
-import org.eclipse.ui.forms.widgets.ScrolledForm;
-import org.osgi.framework.Constants;
 
 /**
  * Editor to browse, analyze and modify an OSGi distribution
  */
 public class DistributionEditor extends FormEditor implements SlcNames {
-       private final static Log log = LogFactory.getLog(DistributionEditor.class);
+       // private final static Log log =
+       // LogFactory.getLog(DistributionEditor.class);
        public final static String ID = DistPlugin.ID + ".distributionEditor";
 
        private Session session;
index 632bd00ea42dd51c688a6d3f4d2f0405cf4dbce1..d7d578a03eb5ce3d811caface211539a46a54d90 100644 (file)
@@ -1,9 +1,11 @@
 package org.argeo.slc.client.ui.dist.editors;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.query.QueryManager;
@@ -15,6 +17,7 @@ import javax.jcr.query.qom.Selector;
 
 import org.argeo.eclipse.ui.ErrorFeedback;
 import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.client.ui.dist.utils.NodeViewerComparator;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
@@ -23,6 +26,8 @@ import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.jface.viewers.TableViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Table;
@@ -37,6 +42,8 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
        private TableViewer viewer;
        private Session session;
 
+       private NodeViewerComparator comparator;
+
        public DistributionOverviewPage(FormEditor formEditor, String title,
                        Session session) {
                super(formEditor, "distributionPage", title);
@@ -49,6 +56,10 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                GridLayout layout = new GridLayout(1, false);
                form.getBody().setLayout(layout);
 
+               // helpers to enable sorting by column
+               List<String> propertiesList = new ArrayList<String>();
+               List<Integer> propertyTypesList = new ArrayList<Integer>();
+
                // Define the TableViewer
                viewer = new TableViewer(form.getBody(), SWT.MULTI | SWT.H_SCROLL
                                | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
@@ -62,6 +73,10 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                                return JcrUtils.get((Node) element, SLC_SYMBOLIC_NAME);
                        }
                });
+               col.getColumn().addSelectionListener(getSelectionAdapter(0));
+               propertiesList.add(SLC_SYMBOLIC_NAME);
+               propertyTypesList.add(PropertyType.STRING);
+
                col = new TableViewerColumn(viewer, SWT.NONE);
                col.getColumn().setWidth(100);
                col.getColumn().setText("Version");
@@ -71,6 +86,10 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                                return JcrUtils.get((Node) element, SLC_BUNDLE_VERSION);
                        }
                });
+               col.getColumn().addSelectionListener(getSelectionAdapter(1));
+               propertiesList.add(SLC_BUNDLE_VERSION);
+               propertyTypesList.add(PropertyType.STRING);
+
                col = new TableViewerColumn(viewer, SWT.NONE);
                col.getColumn().setWidth(150);
                col.getColumn().setText("Group ID");
@@ -80,6 +99,10 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                                return JcrUtils.get((Node) element, SLC_GROUP_ID);
                        }
                });
+               col.getColumn().addSelectionListener(getSelectionAdapter(2));
+               propertiesList.add(SLC_GROUP_ID);
+               propertyTypesList.add(PropertyType.STRING);
+
                col = new TableViewerColumn(viewer, SWT.NONE);
                col.getColumn().setWidth(300);
                col.getColumn().setText("Name");
@@ -90,6 +113,9 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                                                + Constants.BUNDLE_NAME);
                        }
                });
+               col.getColumn().addSelectionListener(getSelectionAdapter(3));
+               propertiesList.add(SLC_ + Constants.BUNDLE_NAME);
+               propertyTypesList.add(PropertyType.STRING);
 
                final Table table = viewer.getTable();
                table.setHeaderVisible(true);
@@ -98,6 +124,10 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
 
                viewer.setContentProvider(new DistributionsContentProvider());
                viewer.setInput(session);
+               comparator = new NodeViewerComparator(1,
+                               NodeViewerComparator.DESCENDING, propertiesList,
+                               propertyTypesList);
+               viewer.setComparator(comparator);
        }
 
        @Override
@@ -125,6 +155,26 @@ class DistributionOverviewPage extends FormPage implements SlcNames {
                return result.getNodes();
        }
 
+       private SelectionAdapter getSelectionAdapter(final int index) {
+               SelectionAdapter selectionAdapter = new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               Table table = viewer.getTable();
+                               comparator.setColumn(index);
+                               int dir = table.getSortDirection();
+                               if (table.getSortColumn() == table.getColumn(index)) {
+                                       dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+                               } else {
+                                       dir = SWT.DOWN;
+                               }
+                               table.setSortDirection(dir);
+                               table.setSortColumn(table.getColumn(index));
+                               viewer.refresh();
+                       }
+               };
+               return selectionAdapter;
+       }
+
        private static class DistributionsContentProvider implements
                        IStructuredContentProvider {
                private Session session;
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/CommandHelpers.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/CommandHelpers.java
new file mode 100644 (file)
index 0000000..ebd8826
--- /dev/null
@@ -0,0 +1,144 @@
+package org.argeo.slc.client.ui.dist.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.ArgeoException;
+import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.Parameterization;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.menus.CommandContributionItem;
+import org.eclipse.ui.menus.CommandContributionItemParameter;
+import org.eclipse.ui.services.IServiceLocator;
+
+/**
+ * Centralizes useful methods to manage command updates
+ */
+public class CommandHelpers {
+
+       /**
+        * Refresh the given command. 
+        */
+       public static void refreshCommand(IMenuManager menuManager,
+                       IServiceLocator locator, String cmdId, String label, String iconPath,
+                       boolean showCommand) {
+               IContributionItem ici = menuManager.find(cmdId);
+               if (ici != null)
+                       menuManager.remove(ici);
+
+               if (showCommand) {
+                       // Set Params
+                       CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter(
+                                       locator, null, cmdId, SWT.PUSH);
+                       contributionItemParameter.label = label;
+                       contributionItemParameter.icon = DistPlugin.getImageDescriptor(iconPath);
+                       CommandContributionItem cci = new CommandContributionItem(
+                                       contributionItemParameter);
+                       cci.setId(cmdId);
+                       menuManager.add(cci);
+               }
+       }
+
+       /**
+        * Refresh the given command and optionally corresponding parameters.
+        * 
+        * @param menuManager
+        * @param locator
+        * @param cmdId
+        * @param label
+        * @param showCommand
+        *            Command must be explicitly removed from the context menu at
+        *            each refresh setting this to false.
+        * @param params
+        *            maps a paramId with a String value
+        */
+       public static void refreshParameterizedCommand(IMenuManager menuManager,
+                       IServiceLocator locator, String cmdId, String label, String iconPath,
+                       boolean showCommand, Map<String, String> params) {
+               IContributionItem ici = menuManager.find(cmdId);
+               if (ici != null)
+                       menuManager.remove(ici);
+               
+               if (showCommand) {
+                       // Set Params
+                       CommandContributionItemParameter contributionItemParameter = new CommandContributionItemParameter(
+                                       locator, null, cmdId, SWT.PUSH);
+                       contributionItemParameter.label = label;
+                       contributionItemParameter.icon = DistPlugin.getImageDescriptor(iconPath);
+
+                       if (params != null)
+                               contributionItemParameter.parameters = params;
+
+                       CommandContributionItem cci = new CommandContributionItem(
+                                       contributionItemParameter);
+                       cci.setId(cmdId);
+                       menuManager.add(cci);
+               }
+       }
+
+       /** Helper to call a command without parameter easily */
+       public static void callCommand(String commandID) {
+               callCommand(commandID, null);
+       }
+
+       /** Helper to call a command with a single parameter easily */
+       public static void callCommand(String commandID, String parameterID,
+                       String parameterValue) {
+               Map<String, String> params = new HashMap<String, String>();
+               params.put(parameterID, parameterValue);
+               callCommand(commandID, params);
+       }
+
+       /**
+        * Helper to call a command with a map of parameters easily
+        * 
+        * @param paramMap
+        *            a map that links various commands ids with corresponding
+        *            String values.
+        */
+       public static void callCommand(String commandID,
+                       Map<String, String> paramMap) {
+               try {
+                       IWorkbench iw = DistPlugin.getDefault().getWorkbench();
+                       IHandlerService handlerService = (IHandlerService) iw
+                                       .getService(IHandlerService.class);
+                       ICommandService cmdService = (ICommandService) iw
+                                       .getActiveWorkbenchWindow().getService(
+                                                       ICommandService.class);
+                       Command cmd = cmdService.getCommand(commandID);
+
+                       ArrayList<Parameterization> parameters = null;
+                       ParameterizedCommand pc; 
+
+                       if (paramMap != null) {
+                               // Set parameters of the command to launch :
+                               parameters = new ArrayList<Parameterization>();
+                               Parameterization parameterization;
+                               for (String id : paramMap.keySet()) {
+                                       parameterization = new Parameterization(
+                                                       cmd.getParameter(id), paramMap.get(id));
+                                       parameters.add(parameterization);
+                               }
+                               pc = new ParameterizedCommand(cmd,
+                                               parameters.toArray(new Parameterization[parameters.size()]));
+                       } else 
+                               pc = new ParameterizedCommand(cmd, null);
+                       
+                       // build the parameterized command
+                       // execute the command
+                       handlerService.executeCommand(pc, null);
+               } catch (Exception e) {
+                       throw new ArgeoException(
+                                       "Unexepected exception while opening node editor", e);
+               }
+       }
+
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/NodeViewerComparator.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/utils/NodeViewerComparator.java
new file mode 100644 (file)
index 0000000..8a0ad60
--- /dev/null
@@ -0,0 +1,151 @@
+package org.argeo.slc.client.ui.dist.utils;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFormatException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.GenericTableComparator;
+import org.eclipse.jface.viewers.Viewer;
+
+public class NodeViewerComparator extends GenericTableComparator {
+       private final static Log log = LogFactory
+                       .getLog(NodeViewerComparator.class);
+
+       protected List<String> propertiesList;
+       protected List<Integer> propertyTypesList;
+       protected Integer propertyType;
+       protected String property;
+
+       public NodeViewerComparator(int defaultColIndex, int defaultDirection,
+                       List<String> propertiesList, List<Integer> propertyTypesList) {
+               super(defaultColIndex, defaultDirection);
+               this.propertiesList = propertiesList;
+               this.propertyTypesList = propertyTypesList;
+               this.propertyIndex = defaultColIndex;
+               this.propertyType = propertyTypesList.get(defaultColIndex);
+               this.property = propertiesList.get(defaultColIndex);
+               setColumn(defaultColIndex);
+       }
+
+       @Override
+       public int compare(Viewer viewer, Object e1, Object e2) {
+               int rc = 0;
+               long lc = 0;
+
+               try {
+                       Node n1 = (Node) e1;
+                       Node n2 = (Node) e2;
+
+                       Value v1 = null;
+                       Value v2 = null;
+                       if (n1.hasProperty(property))
+                               v1 = n1.getProperty(property).getValue();
+                       if (n2.hasProperty(property))
+                               v2 = n2.getProperty(property).getValue();
+
+                       if (v2 == null && v1 == null)
+                               return 0;
+                       else if (v2 == null)
+                               return -1;
+                       else if (v1 == null)
+                               return 1;
+
+                       switch (propertyType) {
+                       case PropertyType.STRING:
+                               rc = v1.getString().compareTo(v2.getString());
+                               break;
+                       case PropertyType.BOOLEAN:
+                               boolean b1 = v1.getBoolean();
+                               boolean b2 = v2.getBoolean();
+                               if (b1 == b2)
+                                       rc = 0;
+                               else
+                                       // we assume true is greater than false
+                                       rc = b1 ? 1 : -1;
+                               break;
+                       case PropertyType.DATE:
+                               Calendar c1 = v1.getDate();
+                               Calendar c2 = v2.getDate();
+                               if (c1 == null || c2 == null)
+                                       log.trace("undefined date");
+                               lc = c1.getTimeInMillis() - c2.getTimeInMillis();
+                               if (lc < Integer.MIN_VALUE)
+                                       // rc = Integer.MIN_VALUE;
+                                       rc = -1;
+                               else if (lc > Integer.MAX_VALUE)
+                                       // rc = Integer.MAX_VALUE;
+                                       rc = 1;
+                               else
+                                       rc = (int) lc;
+                               break;
+                       case PropertyType.LONG:
+                               long l1;
+                               long l2;
+                               // FIXME sometimes an empty string is set instead of the id 
+                               try {
+                                       l1 = v1.getLong();
+                               } catch (ValueFormatException ve) {
+                                       l1 = 0;
+                               }
+                               try {
+                                       l2 = v2.getLong();
+                               } catch (ValueFormatException ve) {
+                                       l2 = 0;
+                               }
+
+                               lc = l1 - l2;
+                               if (lc < Integer.MIN_VALUE)
+                                       // rc = Integer.MIN_VALUE;
+                                       rc = -1;
+                               else if (lc > Integer.MAX_VALUE)
+                                       // rc = Integer.MAX_VALUE;
+                                       rc = 1;
+                               else
+                                       rc = (int) lc;
+                               break;
+                       case PropertyType.DECIMAL:
+                               BigDecimal bd1 = v1.getDecimal();
+                               BigDecimal bd2 = v2.getDecimal();
+                               rc = bd1.compareTo(bd2);
+                               break;
+                       default:
+                               throw new ArgeoException(
+                                               "Unimplemented comparaison for PropertyType "
+                                                               + propertyType);
+                       }
+
+                       // If descending order, flip the direction
+                       if (direction == DESCENDING) {
+                               rc = -rc;
+                       }
+
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Unexpected error "
+                                       + "while comparing nodes", re);
+               }
+               return rc;
+       }
+
+       @Override
+       public void setColumn(int column) {
+               if (column == this.propertyIndex) {
+                       // Same column as last sort; toggle the direction
+                       direction = 1 - direction;
+               } else {
+                       // New column; do a descending sort
+                       this.propertyIndex = column;
+                       this.propertyType = propertyTypesList.get(column);
+                       this.property = propertiesList.get(column);
+                       direction = ASCENDING;
+               }
+       }
+}
\ No newline at end of file
index 7ec83600f2e13abb07c9bb59115ddcd6351c9475..e714a780bd62660d1c1d97e71ecaa701bc160c9e 100644 (file)
@@ -15,6 +15,9 @@
  */
 package org.argeo.slc.client.ui.dist.views;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -25,9 +28,17 @@ import org.argeo.eclipse.ui.AbstractTreeContentProvider;
 import org.argeo.eclipse.ui.ErrorFeedback;
 import org.argeo.eclipse.ui.TreeParent;
 import org.argeo.slc.client.ui.dist.DistPlugin;
+import org.argeo.slc.client.ui.dist.commands.CopyWorkspace;
+import org.argeo.slc.client.ui.dist.commands.CreateWorkspace;
+import org.argeo.slc.client.ui.dist.commands.DeleteWorkspace;
+import org.argeo.slc.client.ui.dist.commands.ManageWorkspaceAuth;
 import org.argeo.slc.client.ui.dist.editors.DistributionEditor;
 import org.argeo.slc.client.ui.dist.editors.DistributionEditorInput;
+import org.argeo.slc.client.ui.dist.utils.CommandHelpers;
 import org.argeo.slc.jcr.SlcNames;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
@@ -36,7 +47,9 @@ import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.TreeViewerColumn;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
 import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.ViewPart;
 
@@ -75,7 +88,19 @@ public class DistributionsView extends ViewPart implements SlcNames {
 
                viewer.setContentProvider(new DistributionsContentProvider());
                viewer.addDoubleClickListener(new DistributionsDCL());
+
+               MenuManager menuManager = new MenuManager();
+               Menu menu = menuManager.createContextMenu(viewer.getTree());
+               menuManager.addMenuListener(new IMenuListener() {
+                       public void menuAboutToShow(IMenuManager manager) {
+                               contextMenuAboutToShow(manager);
+                       }
+               });
+               viewer.getTree().setMenu(menu);
+               getSite().registerContextMenu(menuManager, viewer);
+
                viewer.setInput(getSite());
+
        }
 
        @Override
@@ -83,10 +108,58 @@ public class DistributionsView extends ViewPart implements SlcNames {
                viewer.getTree().setFocus();
        }
 
+       /**
+        * Force refresh of the whole view
+        */
+       public void refresh() {
+               viewer.setContentProvider(new DistributionsContentProvider());
+       }
+
        public void setRepository(Repository repository) {
                this.repository = repository;
        }
 
+       /** Programatically configure the context menu */
+       protected void contextMenuAboutToShow(IMenuManager menuManager) {
+               IWorkbenchWindow window = DistPlugin.getDefault().getWorkbench()
+                               .getActiveWorkbenchWindow();
+               // Get Current selected item :
+               Object firstElement = ((IStructuredSelection) viewer.getSelection())
+                               .getFirstElement();
+               String wsName = null;
+               if (firstElement instanceof TreeParent) {
+                       wsName = ((TreeParent) firstElement).getName();
+               }
+
+               // Build conditions depending on element type (repo or workspace)
+
+               // create workspace
+               CommandHelpers.refreshCommand(menuManager, window, CreateWorkspace.ID,
+                               CreateWorkspace.DEFAULT_LABEL,
+                               CreateWorkspace.DEFAULT_ICON_PATH, true);
+
+               // Copy workspace
+               Map<String, String> params = new HashMap<String, String>();
+               params.put(CopyWorkspace.PARAM_WORKSPACE_NAME, wsName);
+               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               CopyWorkspace.ID, CopyWorkspace.DEFAULT_LABEL,
+                               CopyWorkspace.DEFAULT_ICON_PATH, true, params);
+
+               // Delete Workspace
+               params = new HashMap<String, String>();
+               params.put(DeleteWorkspace.PARAM_WORKSPACE_NAME, wsName);
+               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               DeleteWorkspace.ID, DeleteWorkspace.DEFAULT_LABEL,
+                               DeleteWorkspace.DEFAULT_ICON_PATH, true, params);
+
+               // Manage workspace authorizations
+               params = new HashMap<String, String>();
+               params.put(ManageWorkspaceAuth.PARAM_WORKSPACE_NAME, wsName);
+               CommandHelpers.refreshParameterizedCommand(menuManager, window,
+                               ManageWorkspaceAuth.ID, ManageWorkspaceAuth.DEFAULT_LABEL,
+                               ManageWorkspaceAuth.DEFAULT_ICON_PATH, true, params);
+       }
+
        private class DistributionsContentProvider extends
                        AbstractTreeContentProvider {
 
@@ -160,4 +233,5 @@ public class DistributionsView extends ViewPart implements SlcNames {
                }
 
        }
+
 }
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChangeRightsWizard.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChangeRightsWizard.java
new file mode 100644 (file)
index 0000000..772a8c2
--- /dev/null
@@ -0,0 +1,49 @@
+package org.argeo.slc.client.ui.dist.wizards;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.wizard.Wizard;
+
+/**
+ * Small wizard to manage authorizations on the root node of the current
+ * workspace
+ */
+public class ChangeRightsWizard extends Wizard {
+
+       private Session currentSession;
+
+       // This page widget
+       private ChooseRightsPage page;
+
+       public ChangeRightsWizard(Session currentSession) {
+               super();
+               this.currentSession = currentSession;
+       }
+
+       @Override
+       public void addPages() {
+               try {
+                       page = new ChooseRightsPage();
+                       addPage(page);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot add page to wizard ", e);
+               }
+       }
+
+       @Override
+       public boolean performFinish() {
+               if (!canFinish())
+                       return false;
+               try {
+                       JcrUtils.addPrivilege(currentSession, "/", page.getGroupName(),
+                                       page.getAuthTypeStr());
+               } catch (RepositoryException re) {
+                       throw new ArgeoException(
+                                       "Unexpected error while setting privileges", re);
+               }
+               return true;
+       }
+}
diff --git a/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChooseRightsPage.java b/eclipse/plugins/org.argeo.slc.client.ui.dist/src/main/java/org/argeo/slc/client/ui/dist/wizards/ChooseRightsPage.java
new file mode 100644 (file)
index 0000000..9c3572e
--- /dev/null
@@ -0,0 +1,94 @@
+package org.argeo.slc.client.ui.dist.wizards;
+
+import java.util.regex.Pattern;
+
+import javax.jcr.security.Privilege;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class ChooseRightsPage extends WizardPage implements ModifyListener {
+
+       // This page widget
+       private Text groupNameTxt;
+       private Combo authorizationCmb;
+
+       // Define acceptable chars for the technical name
+       private static Pattern p = Pattern.compile("^[A-Za-z0-9]+$");
+
+       // USABLE SHORTCUTS
+       protected final static String[] validAuthType = { Privilege.JCR_READ,
+                       Privilege.JCR_WRITE, Privilege.JCR_ALL };
+
+       public ChooseRightsPage() {
+               super("Main");
+               setTitle("Manange authorizations on the current workspace");
+       }
+
+       public void createControl(Composite parent) {
+               // specify subject
+               Composite composite = new Composite(parent, SWT.NONE);
+               composite.setLayout(new GridLayout(2, false));
+               Label lbl = new Label(composite, SWT.LEAD);
+               lbl.setText("Group or user name (no blank, no special chars)");
+               lbl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+               groupNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER);
+               groupNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
+                               false));
+               if (groupNameTxt != null)
+                       groupNameTxt.addModifyListener(this);
+
+               // Choose rigths
+               new Label(composite, SWT.NONE).setText("Choose corresponding rights");
+               authorizationCmb = new Combo(composite, SWT.BORDER | SWT.V_SCROLL);
+               authorizationCmb.setItems(validAuthType);
+               GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+               authorizationCmb.setLayoutData(gd);
+
+               authorizationCmb.select(0);
+
+               // Compulsory
+               setControl(composite);
+       }
+
+       protected String getGroupName() {
+               return groupNameTxt.getText();
+       }
+
+       protected String getAuthTypeStr() {
+               return authorizationCmb.getItem(authorizationCmb.getSelectionIndex());
+       }
+
+       private static boolean match(String s) {
+               return p.matcher(s).matches();
+       }
+
+       public void modifyText(ModifyEvent event) {
+               String message = checkComplete();
+               if (message != null)
+                       setMessage(message, WizardPage.ERROR);
+               else {
+                       setMessage("Complete", WizardPage.INFORMATION);
+                       setPageComplete(true);
+               }
+       }
+
+       /** @return error message or null if complete */
+       protected String checkComplete() {
+               String groupStr = groupNameTxt.getText();
+               if (groupStr == null || "".equals(groupStr))
+                       return "Please enter a short technical name for the new repository.";
+               else if (!match(groupStr))
+                       return "Please use only alphanumerical chars for the short technical name.";
+
+               return null;
+       }
+}