Some tries for the users
authorBruno Sinou <bsinou@argeo.org>
Fri, 12 Dec 2014 17:25:53 +0000 (17:25 +0000)
committerBruno Sinou <bsinou@argeo.org>
Fri, 12 Dec 2014 17:25:53 +0000 (17:25 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@7574 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.cms/pom.xml
org.argeo.cms/src/org/argeo/cms/maintenance/Browse.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/MaintenanceStyles.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/NonAdminPage.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/users/Users.java [new file with mode: 0644]
org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java [new file with mode: 0644]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java [deleted file]
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/views/UsersView.java
org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/wizards/UserBatchUpdateWizard.java

index f2a470882fef893867f4c23e863209b939ddbf34..4833692aa5b01962f80ee5a5e2bab5651fcf4d02 100644 (file)
                        <groupId>org.argeo.tp.rap.platform</groupId>
                        <artifactId>org.eclipse.core.commands</artifactId>
                </dependency>
+               <!--  Argeo base Eclipse utilities. -->
+               <dependency>
+                       <groupId>org.argeo.commons</groupId>
+                       <artifactId>org.argeo.eclipse.ui</artifactId>
+                       <version>2.1.12-SNAPSHOT</version>
+               </dependency>
+
 
                <!-- OSGi -->
                <dependency>
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/Browse.java b/org.argeo.cms/src/org/argeo/cms/maintenance/Browse.java
new file mode 100644 (file)
index 0000000..2195e57
--- /dev/null
@@ -0,0 +1,595 @@
+package org.argeo.cms.maintenance;
+
+import static javax.jcr.Node.JCR_CONTENT;
+import static org.eclipse.swt.SWT.RIGHT;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.LinkedHashMap;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.CmsLink;
+import org.argeo.cms.CmsTypes;
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.CmsUtils;
+import org.argeo.cms.text.Img;
+import org.argeo.cms.widgets.EditableImage;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ILazyContentProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+
+public class Browse implements CmsUiProvider {
+
+       // Some local constants to experiment. should be cleaned
+       private final static String BROWSE_PREFIX = "#browse";
+       private final static int THUMBNAIL_WIDTH = 400;
+       private final static int COLUMN_WIDTH = 160;
+
+       // keep a cache of the opened nodes
+       // Key is the path
+       private LinkedHashMap<String, FilterEntitiesVirtualTable> browserCols = new LinkedHashMap<String, Browse.FilterEntitiesVirtualTable>();
+       private Composite nodeDisplayParent;
+       private Composite colViewer;
+       private ScrolledComposite scrolledCmp;
+       private Text parentPathTxt;
+       private Text filterTxt;
+       private Node currEdited;
+
+       private String initialPath;
+
+       @Override
+       public Control createUi(Composite parent, Node context)
+                       throws RepositoryException {
+               if (context == null)
+                       throw new CmsException("Context cannot be null");
+               GridLayout layout = CmsUtils.noSpaceGridLayout();
+               layout.numColumns = 2;
+               parent.setLayout(layout);
+
+               // Left
+               Composite leftCmp = new Composite(parent, SWT.NO_FOCUS);
+               leftCmp.setLayoutData(CmsUtils.fillAll());
+               createBrowserPart(leftCmp, context);
+
+               // Right
+               nodeDisplayParent = new Composite(parent, SWT.NO_FOCUS | SWT.BORDER);
+               GridData gd = new GridData(SWT.RIGHT, SWT.FILL, false, true);
+               gd.widthHint = THUMBNAIL_WIDTH;
+               nodeDisplayParent.setLayoutData(gd);
+               createNodeView(nodeDisplayParent, context);
+
+               // INIT
+               setEdited(context);
+               initialPath = context.getPath();
+
+               // Workaround we don't yet manage the delete to display parent of the
+               // initial context node
+
+               return null;
+       }
+
+       private void createBrowserPart(Composite parent, Node context)
+                       throws RepositoryException {
+               GridLayout layout = CmsUtils.noSpaceGridLayout();
+               parent.setLayout(layout);
+               Composite filterCmp = new Composite(parent, SWT.NO_FOCUS);
+               filterCmp.setLayoutData(CmsUtils.fillWidth());
+
+               // top filter
+               addFilterPanel(filterCmp);
+
+               // scrolled composite
+               scrolledCmp = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.BORDER
+                               | SWT.NO_FOCUS);
+               scrolledCmp.setLayoutData(CmsUtils.fillAll());
+               scrolledCmp.setExpandVertical(true);
+               scrolledCmp.setExpandHorizontal(true);
+               scrolledCmp.setShowFocusedControl(true);
+
+               colViewer = new Composite(scrolledCmp, SWT.NO_FOCUS);
+               scrolledCmp.setContent(colViewer);
+               scrolledCmp.addControlListener(new ControlAdapter() {
+                       private static final long serialVersionUID = 6589392045145698201L;
+
+                       @Override
+                       public void controlResized(ControlEvent e) {
+                               Rectangle r = scrolledCmp.getClientArea();
+                               scrolledCmp.setMinSize(colViewer.computeSize(SWT.DEFAULT,
+                                               r.height));
+                       }
+               });
+               initExplorer(colViewer, context);
+       }
+
+       private Control initExplorer(Composite parent, Node context)
+                       throws RepositoryException {
+               parent.setLayout(CmsUtils.noSpaceGridLayout());
+               createBrowserColumn(parent, context);
+               return null;
+       }
+
+       private Control createBrowserColumn(Composite parent, Node context)
+                       throws RepositoryException {
+               // TODO style is not correctly managed.
+               FilterEntitiesVirtualTable table = new FilterEntitiesVirtualTable(
+                               parent, SWT.BORDER | SWT.NO_FOCUS, context);
+               // CmsUtils.style(table, ArgeoOrgStyle.browserColumn.style());
+               table.filterList("*");
+               table.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true));
+               browserCols.put(context.getPath(), table);
+               return null;
+       }
+
+       public void addFilterPanel(Composite parent) {
+
+               parent.setLayout(CmsUtils.noSpaceGridLayout(new GridLayout(2, false)));
+
+               // Text Area for the filter
+               parentPathTxt = new Text(parent, SWT.NO_FOCUS);
+               parentPathTxt.setEditable(false);
+               filterTxt = new Text(parent, SWT.SEARCH | SWT.ICON_CANCEL);
+               filterTxt.setMessage("Filter current list");
+               filterTxt.setLayoutData(CmsUtils.fillWidth());
+               filterTxt.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = 7709303319740056286L;
+
+                       public void modifyText(ModifyEvent event) {
+                               modifyFilter(false);
+                       }
+               });
+
+               filterTxt.addKeyListener(new KeyListener() {
+                       private static final long serialVersionUID = -4523394262771183968L;
+
+                       @Override
+                       public void keyReleased(KeyEvent e) {
+                       }
+
+                       @Override
+                       public void keyPressed(KeyEvent e) {
+                               boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
+                               // boolean altPressed = (e.stateMask & SWT.ALT) != 0;
+                               FilterEntitiesVirtualTable currTable = null;
+                               if (currEdited != null) {
+                                       FilterEntitiesVirtualTable table = browserCols
+                                                       .get(getPath(currEdited));
+                                       if (table != null && !table.isDisposed())
+                                               currTable = table;
+                               }
+
+                               try {
+                                       if (e.keyCode == SWT.ARROW_DOWN)
+                                               currTable.setFocus();
+                                       else if (e.keyCode == SWT.BS) {
+                                               if (filterTxt.getText().equals("")
+                                                               && !(getPath(currEdited).equals("/") || getPath(
+                                                                               currEdited).equals(initialPath))) {
+                                                       setEdited(currEdited.getParent());
+                                                       e.doit = false;
+                                                       filterTxt.setFocus();
+                                               }
+                                       } else if (e.keyCode == SWT.TAB && !shiftPressed) {
+                                               if (currEdited.getNodes(filterTxt.getText() + "*")
+                                                               .getSize() == 1) {
+                                                       setEdited(currEdited.getNodes(
+                                                                       filterTxt.getText() + "*").nextNode());
+                                               }
+                                               filterTxt.setFocus();
+                                               e.doit = false;
+                                       }
+                               } catch (RepositoryException e1) {
+                                       throw new ArgeoException(
+                                                       "Unexpected error in key management for "
+                                                                       + currEdited + "with filter "
+                                                                       + filterTxt.getText(), e1);
+                               }
+
+                       }
+               });
+       }
+
+       private void setEdited(Node node) {
+               try {
+                       currEdited = node;
+                       CmsUtils.clear(nodeDisplayParent);
+                       createNodeView(nodeDisplayParent, currEdited);
+                       nodeDisplayParent.layout();
+                       refreshFilters(node);
+                       refreshBrowser(node);
+               } catch (RepositoryException re) {
+                       throw new ArgeoException("Unable to update browser for " + node, re);
+               }
+       }
+
+       private void refreshFilters(Node node) throws RepositoryException {
+               String currNodePath = node.getPath();
+               parentPathTxt.setText(currNodePath);
+               filterTxt.setText("");
+               filterTxt.getParent().layout();
+       }
+
+       private void refreshBrowser(Node node) throws RepositoryException {
+
+               // Retrieve
+               String currNodePath = node.getPath();
+               String currParPath = "";
+               if (!"/".equals(currNodePath))
+                       currParPath = JcrUtils.parentPath(currNodePath);
+               if ("".equals(currParPath))
+                       currParPath = "/";
+
+               Object[][] colMatrix = new Object[browserCols.size()][2];
+
+               int i = 0, j = -1, k = -1;
+               for (String path : browserCols.keySet()) {
+                       colMatrix[i][0] = path;
+                       colMatrix[i][1] = browserCols.get(path);
+                       if (j >= 0 && k < 0 && !currNodePath.equals("/")) {
+                               boolean leaveOpened = path.startsWith(currNodePath);
+
+                               // workaround for same name siblings
+                               if (leaveOpened
+                                               && (path.lastIndexOf("/") == 0
+                                                               && currNodePath.lastIndexOf("/") == 0 || JcrUtils
+                                                               .parentPath(path).equals(
+                                                                               JcrUtils.parentPath(currNodePath))))
+                                       leaveOpened = JcrUtils.lastPathElement(path).equals(
+                                                       JcrUtils.lastPathElement(currNodePath));
+
+                               if (!leaveOpened)
+                                       k = i;
+                       }
+                       if (currParPath.equals(path))
+                               j = i;
+                       i++;
+               }
+
+               if (j >= 0 && k >= 0)
+                       // remove useless cols
+                       for (int l = i - 1; l >= k; l--) {
+                               browserCols.remove(colMatrix[l][0]);
+                               ((FilterEntitiesVirtualTable) colMatrix[l][1]).dispose();
+                       }
+
+               if (!browserCols.containsKey(currNodePath))
+                       createBrowserColumn(colViewer, node);
+
+               colViewer.setLayout(CmsUtils.noSpaceGridLayout(new GridLayout(
+                               browserCols.size(), false)));
+               // colViewer.pack();
+               colViewer.layout();
+               // also resize the scrolled composite
+               scrolledCmp.layout();
+               scrolledCmp.getShowFocusedControl();
+               // colViewer.getParent().layout();
+               // if (JcrUtils.parentPath(currNodePath).equals(currBrowserKey)) {
+               // } else {
+               // }
+       }
+
+       private void modifyFilter(boolean fromOutside) {
+               if (!fromOutside)
+                       if (currEdited != null) {
+                               String filter = filterTxt.getText() + "*";
+                               FilterEntitiesVirtualTable table = browserCols
+                                               .get(getPath(currEdited));
+                               if (table != null && !table.isDisposed())
+                                       table.filterList(filter);
+                       }
+
+       }
+
+       private String getPath(Node node) {
+               try {
+                       return node.getPath();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Unable to get path for node " + node, e);
+               }
+       }
+
+       private Point imageWidth = new Point(250, 0);
+
+       private Control createNodeView(Composite parent, Node context)
+                       throws RepositoryException {
+
+               parent.setLayout(new GridLayout(2, false));
+
+               if (isImg(context)) {
+                       EditableImage image = new Img(parent, RIGHT, context, imageWidth);
+                       image.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true,
+                                       false, 2, 1));
+               }
+
+               // Name and primary type
+               Label contextL = new Label(parent, SWT.NONE);
+               contextL.setData(RWT.MARKUP_ENABLED, true);
+               contextL.setText("<b>" + context.getName() + "</b>");
+               new Label(parent, SWT.NONE).setText(context.getPrimaryNodeType()
+                               .getName());
+
+               // Children
+               for (NodeIterator nIt = context.getNodes(); nIt.hasNext();) {
+                       Node child = nIt.nextNode();
+                       new CmsLink(child.getName(), BROWSE_PREFIX + child.getPath())
+                                       .createUi(parent, context);
+                       new Label(parent, SWT.NONE).setText(child.getPrimaryNodeType()
+                                       .getName());
+               }
+
+               // Properties
+               for (PropertyIterator pIt = context.getProperties(); pIt.hasNext();) {
+                       Property property = pIt.nextProperty();
+                       Label label = new Label(parent, SWT.NONE);
+                       label.setText(property.getName());
+                       label.setToolTipText(JcrUtils
+                                       .getPropertyDefinitionAsString(property));
+                       new Label(parent, SWT.NONE).setText(getPropAsString(property));
+               }
+
+               return null;
+       }
+
+       private boolean isImg(Node node) throws RepositoryException {
+               return node.hasNode(JCR_CONTENT) && node.isNodeType(CmsTypes.CMS_IMAGE);
+       }
+
+       private String getPropAsString(Property property)
+                       throws RepositoryException {
+               String result = "";
+               DateFormat timeFormatter = new SimpleDateFormat("");
+               if (property.isMultiple()) {
+                       result = getMultiAsString(property, ", ");
+               } else {
+                       Value value = property.getValue();
+                       if (value.getType() == PropertyType.BINARY)
+                               result = "<binary>";
+                       else if (value.getType() == PropertyType.DATE)
+                               result = timeFormatter.format(value.getDate().getTime());
+                       else
+                               result = value.getString();
+               }
+               return result;
+       }
+
+       private String getMultiAsString(Property property, String separator)
+                       throws RepositoryException {
+               if (separator == null)
+                       separator = "; ";
+               Value[] values = property.getValues();
+               StringBuilder builder = new StringBuilder();
+               for (Value val : values) {
+                       String currStr = val.getString();
+                       if (!"".equals(currStr.trim()))
+                               builder.append(currStr).append(separator);
+               }
+               if (builder.lastIndexOf(separator) >= 0)
+                       return builder.substring(0, builder.length() - separator.length());
+               else
+                       return builder.toString();
+       }
+
+       /** Almost canonical implementation of a table that display entities */
+       private class FilterEntitiesVirtualTable extends Composite {
+               private static final long serialVersionUID = 8798147431706283824L;
+
+               // Context
+               private Node context;
+
+               // UI Objects
+               private TableViewer entityViewer;
+
+               // enable management of multiple columns
+               Node getNode() {
+                       return context;
+               }
+
+               @Override
+               public boolean setFocus() {
+                       if (entityViewer.getTable().isDisposed())
+                               return false;
+                       if (entityViewer.getSelection().isEmpty()) {
+                               Object first = entityViewer.getElementAt(0);
+                               if (first != null) {
+                                       entityViewer.setSelection(new StructuredSelection(first),
+                                                       true);
+                               }
+                       }
+                       return entityViewer.getTable().setFocus();
+               }
+
+               void filterList(String filter) {
+                       try {
+                               NodeIterator nit = context.getNodes(filter);
+                               refreshFilteredList(nit);
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Unable to filter " + getNode()
+                                               + " children with filter " + filter, e);
+                       }
+
+               }
+
+               public FilterEntitiesVirtualTable(Composite parent, int style,
+                               Node context) {
+                       super(parent, SWT.NO_FOCUS);
+                       this.context = context;
+                       populate();
+               }
+
+               protected void populate() {
+                       Composite parent = this;
+                       GridLayout layout = CmsUtils.noSpaceGridLayout();
+
+                       this.setLayout(layout);
+                       createTableViewer(parent);
+               }
+
+               private void createTableViewer(final Composite parent) {
+                       // the list
+                       // We must limit the size of the table otherwise the full list is
+                       // loaded
+                       // before the layout happens
+                       Composite listCmp = new Composite(parent, SWT.NO_FOCUS);
+                       GridData gd = new GridData(SWT.LEFT, SWT.FILL, false, true);
+                       gd.widthHint = COLUMN_WIDTH;
+                       listCmp.setLayoutData(gd);
+                       listCmp.setLayout(CmsUtils.noSpaceGridLayout());
+
+                       entityViewer = new TableViewer(listCmp, SWT.VIRTUAL | SWT.SINGLE);
+                       Table table = entityViewer.getTable();
+
+                       table.setLayoutData(CmsUtils.fillAll());
+                       table.setLinesVisible(true);
+                       table.setHeaderVisible(false);
+                       table.setData(RWT.MARKUP_ENABLED, Boolean.TRUE);
+
+                       CmsUtils.style(table, MaintenanceStyles.BROWSER_COLUMN);
+
+                       // first column
+                       TableViewerColumn column = new TableViewerColumn(entityViewer,
+                                       SWT.NONE);
+                       TableColumn tcol = column.getColumn();
+                       tcol.setWidth(COLUMN_WIDTH);
+                       tcol.setResizable(true);
+                       column.setLabelProvider(new SimpleNameLP());
+
+                       entityViewer.setContentProvider(new MyLazyCP(entityViewer));
+                       entityViewer
+                                       .addSelectionChangedListener(new ISelectionChangedListener() {
+
+                                               @Override
+                                               public void selectionChanged(SelectionChangedEvent event) {
+                                                       IStructuredSelection selection = (IStructuredSelection) entityViewer
+                                                                       .getSelection();
+                                                       if (selection.isEmpty())
+                                                               return;
+                                                       else
+                                                               setEdited((Node) selection.getFirstElement());
+
+                                               }
+                                       });
+
+                       table.addKeyListener(new KeyListener() {
+
+                               @Override
+                               public void keyReleased(KeyEvent e) {
+                               }
+
+                               @Override
+                               public void keyPressed(KeyEvent e) {
+
+                                       IStructuredSelection selection = (IStructuredSelection) entityViewer
+                                                       .getSelection();
+                                       Node selected = null;
+                                       if (!selection.isEmpty())
+                                               selected = ((Node) selection.getFirstElement());
+                                       try {
+                                               if (e.keyCode == SWT.ARROW_RIGHT) {
+                                                       if (selected != null) {
+                                                               setEdited(selected);
+                                                               browserCols.get(selected.getPath()).setFocus();
+                                                       }
+                                               } else if (e.keyCode == SWT.ARROW_LEFT) {
+                                                       try {
+                                                               String newPath = getNode().getParent()
+                                                                               .getPath();
+                                                               if (browserCols.containsKey(newPath))
+                                                                       browserCols.get(newPath).setFocus();
+                                                       } catch (ItemNotFoundException ie) {
+                                                               // root silent
+                                                       }
+                                               }
+                                       } catch (RepositoryException ie) {
+                                               throw new ArgeoException("Error while managing arrow "
+                                                               + "events in the browser for " + selected, ie);
+                                       }
+                               }
+                       });
+               }
+
+               private class MyLazyCP implements ILazyContentProvider {
+                       private static final long serialVersionUID = 1L;
+                       private TableViewer viewer;
+                       private Object[] elements;
+
+                       public MyLazyCP(TableViewer viewer) {
+                               this.viewer = viewer;
+                       }
+
+                       public void dispose() {
+                       }
+
+                       public void inputChanged(Viewer viewer, Object oldInput,
+                                       Object newInput) {
+                               // IMPORTANT: don't forget this: an exception will be thrown if
+                               // a selected object is not part of the results anymore.
+                               viewer.setSelection(null);
+                               this.elements = (Object[]) newInput;
+                       }
+
+                       public void updateElement(int index) {
+                               viewer.replace(elements[index], index);
+                       }
+               }
+
+               protected void refreshFilteredList(NodeIterator children) {
+                       Object[] rows = JcrUtils.nodeIteratorToList(children).toArray();
+                       entityViewer.setInput(rows);
+                       entityViewer.setItemCount(rows.length);
+                       entityViewer.refresh();
+               }
+
+               public class SimpleNameLP extends ColumnLabelProvider {
+                       private static final long serialVersionUID = 2465059387875338553L;
+
+                       @Override
+                       public String getText(Object element) {
+                               if (element instanceof Node) {
+                                       Node curr = ((Node) element);
+                                       try {
+                                               return curr.getName();
+                                       } catch (RepositoryException e) {
+                                               throw new ArgeoException("Unable to get name for"
+                                                               + curr);
+                                       }
+                               }
+                               return super.getText(element);
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/MaintenanceStyles.java b/org.argeo.cms/src/org/argeo/cms/maintenance/MaintenanceStyles.java
new file mode 100644 (file)
index 0000000..fef25d7
--- /dev/null
@@ -0,0 +1,10 @@
+package org.argeo.cms.maintenance;
+
+/** Specific styles used by the various maintenance pages . */
+public interface MaintenanceStyles {
+       // General
+       public final static String PREFIX = "maintenance_";
+
+       // Browser
+       public final static String BROWSER_COLUMN = "browser_column";
+       }
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/NonAdminPage.java b/org.argeo.cms/src/org/argeo/cms/maintenance/NonAdminPage.java
new file mode 100644 (file)
index 0000000..7c1a18a
--- /dev/null
@@ -0,0 +1,30 @@
+package org.argeo.cms.maintenance;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.CmsUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+public class NonAdminPage implements CmsUiProvider{
+
+       @Override
+       public Control createUi(Composite parent, Node context)
+                       throws RepositoryException {
+               Composite body = new Composite(parent, SWT.NO_FOCUS);
+               body.setLayoutData(CmsUtils.fillAll());
+               body.setLayout(new GridLayout());
+               Label label = new Label(body, SWT.NONE);
+               label.setText("You should be an admin to perform maintenance operations. "
+                               + "Are you sure you are logged in?");
+               label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+               return null;
+       }
+       
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/users/Users.java b/org.argeo.cms/src/org/argeo/cms/users/Users.java
new file mode 100644 (file)
index 0000000..c8a9cc4
--- /dev/null
@@ -0,0 +1,145 @@
+package org.argeo.cms.users;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.Privilege;
+
+import org.argeo.cms.CmsUiProvider;
+import org.argeo.cms.CmsUtils;
+import org.argeo.cms.maintenance.NonAdminPage;
+import org.argeo.eclipse.ui.parts.UsersTable;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class Users implements CmsUiProvider {
+
+       NonAdminPage nap = new NonAdminPage();
+
+       @Override
+       public Control createUi(Composite parent, Node context)
+                       throws RepositoryException {
+
+               if (isAdmin(context)) {
+                       Session session = context.getSession().getRepository()
+                                       .login("main");
+                       return createUsersTable(parent, session);
+               } else
+                       nap.createUi(parent, context);
+               return null;
+
+       }
+
+       private Control createUsersTable(Composite parent, final Session session)
+                       throws RepositoryException {
+               // Create the composite that displays the list and a filter
+               UsersTable userTableCmp = new UsersTable(parent, SWT.NO_FOCUS, session);
+               userTableCmp.populate(true, false);
+
+               userTableCmp.setLayoutData(CmsUtils.fillAll());
+
+               userTableCmp.addDisposeListener(new DisposeListener() {
+                       private static final long serialVersionUID = -8854052549807709846L;
+
+                       @Override
+                       public void widgetDisposed(DisposeEvent event) {
+                               JcrUtils.logoutQuietly(session);
+                       }
+               });
+
+               // Configure
+               // userTableCmp.getTableViewer().addDoubleClickListener(
+               // new ViewDoubleClickListener());
+               // getViewSite().setSelectionProvider(userTableCmp.getTableViewer());
+
+               // Add listener to refresh the list when something changes
+               // userStructureListener = new JcrUserListener(getSite().getShell()
+               // .getDisplay());
+               // JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
+               // | Event.NODE_REMOVED, ArgeoJcrConstants.PEOPLE_BASE_PATH, null);
+               // userPropertiesListener = new JcrUserListener(getSite().getShell()
+               // .getDisplay());
+               // JcrUtils.addListener(session, userStructureListener,
+               // Event.PROPERTY_CHANGED | Event.PROPERTY_ADDED
+               // | Event.PROPERTY_REMOVED,
+               // ArgeoJcrConstants.PEOPLE_BASE_PATH,
+               // ArgeoTypes.ARGEO_USER_PROFILE);
+
+               return userTableCmp;
+       }
+
+       private boolean isAdmin(Node node) throws RepositoryException {
+               // FIXME clean this check one new user management policy has been
+               // implemented.
+               AccessControlManager acm = node.getSession().getAccessControlManager();
+               Privilege[] privs = new Privilege[1];
+               privs[0] = acm.privilegeFromName(Privilege.JCR_ALL);
+               return acm.hasPrivileges("/", privs);
+       }
+
+       // @Override
+       // public void dispose() {
+       // JcrUtils.removeListenerQuietly(session, userStructureListener);
+       // JcrUtils.removeListenerQuietly(session, userPropertiesListener);
+       // JcrUtils.logoutQuietly(session);
+       // super.dispose();
+       // }
+       //
+       // // public void setSession(Session session) {
+       // // this.session = session;
+       // // }
+       //
+       // public void refresh() {
+       // this.getSite().getShell().getDisplay().asyncExec(new Runnable() {
+       // @Override
+       // public void run() {
+       // userTableCmp.refresh();
+       // }
+       // });
+       // }
+       //
+       // private class JcrUserListener implements EventListener {
+       // private final Display display;
+       //
+       // public JcrUserListener(Display display) {
+       // super();
+       // this.display = display;
+       // }
+       //
+       // @Override
+       // public void onEvent(EventIterator events) {
+       // display.asyncExec(new Runnable() {
+       // @Override
+       // public void run() {
+       // userTableCmp.refresh();
+       // }
+       // });
+       // }
+       // }
+       //
+       // class ViewDoubleClickListener implements IDoubleClickListener {
+       // public void doubleClick(DoubleClickEvent evt) {
+       // if (evt.getSelection().isEmpty())
+       // return;
+       //
+       // Object obj = ((IStructuredSelection) evt.getSelection())
+       // .getFirstElement();
+       // if (obj instanceof Node) {
+       // try {
+       // String username = ((Node) obj).getProperty(ARGEO_USER_ID)
+       // .getString();
+       // String commandId = OpenArgeoUserEditor.COMMAND_ID;
+       // String paramName = OpenArgeoUserEditor.PARAM_USERNAME;
+       // CommandUtils.callCommand(commandId, paramName, username);
+       // } catch (RepositoryException e) {
+       // throw new ArgeoException("Cannot open user editor", e);
+       // }
+       // }
+       // }
+
+}
diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java
new file mode 100644 (file)
index 0000000..0a7b8d1
--- /dev/null
@@ -0,0 +1,366 @@
+package org.argeo.eclipse.ui.parts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Constraint;
+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 javax.jcr.query.qom.StaticOperand;
+
+import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.eclipse.ui.jcr.JcrUiUtils;
+import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition;
+import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator;
+import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider;
+import org.argeo.eclipse.ui.utils.ViewerUtils;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+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.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+
+public class UsersTable extends Composite implements ArgeoNames {
+       // private final static Log log =
+       // LogFactory.getLog(UserTableComposite.class);
+
+       private static final long serialVersionUID = -7385959046279360420L;
+
+       private TableViewer usersViewer;
+       private Text filterTxt;
+       private final static String FILTER_HELP_MSG = "Type filter criterion "
+                       + "separated by a space";
+       private Session session;
+
+       private Font italic;
+       private Font bold;
+
+       private boolean hasFilter;
+       private boolean hasSelectionColumn;
+
+       // private List<Node> selectedItems = new ArrayList<Node>();
+
+       /**
+        * Overwrite to display other columns
+        */
+       public List<ColumnDefinition> getColumnsDef() {
+               List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
+
+               // User ID
+               columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID,
+                               PropertyType.STRING, "User ID", 100));
+               // Displayed name
+               columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE,
+                               PropertyType.STRING, "Name", 150));
+
+               // E-mail
+               columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL,
+                               PropertyType.STRING, "E-mail", 150));
+
+               // Description
+               columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION,
+                               PropertyType.STRING, "Description", 200));
+
+               return columnDefs;
+       }
+
+       public UsersTable(Composite parent, int style, Session session) {
+               super(parent, style);
+               this.session = session;
+       }
+
+       /**
+        * 
+        * @param addFilter
+        *            choose to add a field to filter results or not
+        * @param addSelection
+        *            choose to add a column to select some of the displayed results
+        *            or not
+        */
+       public void populate(boolean addFilter, boolean addSelection) {
+               // initialization
+               Composite parent = this;
+               italic = EclipseUiUtils.getItalicFont(parent);
+               bold = EclipseUiUtils.getBoldFont(parent);
+               hasFilter = addFilter;
+               hasSelectionColumn = addSelection;
+
+               // Main Layout
+               this.setLayout(new GridLayout(1, false));
+               if (hasFilter)
+                       createFilterPart(parent);
+               usersViewer = createTableViewer(parent);
+               // EclipseUiSpecificUtils.enableToolTipSupport(usersViewer);
+               usersViewer.setContentProvider(new UsersContentProvider());
+               refreshFilteredList();
+       }
+
+       public List<Node> getSelectedUsers() {
+               if (hasSelectionColumn) {
+                       Object[] elements = ((CheckboxTableViewer) usersViewer)
+                                       .getCheckedElements();
+
+                       List<Node> result = new ArrayList<Node>();
+                       for (Object obj : elements) {
+                               result.add((Node) obj);
+                       }
+                       return result;
+               } else
+                       throw new ArgeoException("Unvalid request: no selection column "
+                                       + "has been created for the current table");
+       }
+
+       /** Returns the User table viewer, typically to add doubleclick listener */
+       public TableViewer getTableViewer() {
+               return usersViewer;
+       }
+       
+       /** Returns filter String or null*/
+       protected String getFilterString() {
+               return hasFilter ? filterTxt.getText() : null;
+       }
+       
+       
+
+       private TableViewer createTableViewer(final Composite parent) {
+               int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
+               if (hasSelectionColumn)
+                       style = style | SWT.CHECK;
+
+               Table table = new Table(parent, style);
+               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+               TableViewer viewer;
+               if (hasSelectionColumn)
+                       viewer = new CheckboxTableViewer(table);
+               else
+                       viewer = new TableViewer(table);
+               table.setLinesVisible(true);
+               table.setHeaderVisible(true);
+
+               // pass a mapping between col index and property name to the comparator.
+               // List<String> propertiesList = new ArrayList<String>();
+
+               TableViewerColumn column;
+               int offset = 0;
+               if (hasSelectionColumn) {
+                       offset = 1;
+                       column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE,
+                                       25);
+                       column.setLabelProvider(new ColumnLabelProvider() {
+                               private static final long serialVersionUID = 1L;
+
+                               @Override
+                               public String getText(Object element) {
+                                       return null;
+                               }
+                       });
+                       SelectionAdapter selectionAdapter = new SelectionAdapter() {
+                               private static final long serialVersionUID = 1L;
+
+                               boolean allSelected = false;
+
+                               @Override
+                               public void widgetSelected(SelectionEvent e) {
+                                       allSelected = !allSelected;
+                                       ((CheckboxTableViewer) usersViewer)
+                                                       .setAllChecked(allSelected);
+                               }
+                       };
+                       column.getColumn().addSelectionListener(selectionAdapter);
+               }
+
+               // Create other columns
+               List<ColumnDefinition> colDefs = getColumnsDef();
+
+               NodeViewerComparator comparator = new NodeViewerComparator();
+               int i = offset;
+               for (ColumnDefinition colDef : colDefs) {
+                       column = ViewerUtils.createTableViewerColumn(viewer,
+                                       colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
+                       column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
+                       column.getColumn().addSelectionListener(
+                                       JcrUiUtils.getNodeSelectionAdapter(i,
+                                                       colDef.getPropertyType(), colDef.getPropertyName(),
+                                                       comparator, viewer));
+                       i++;
+               }
+
+               // IMPORTANT: initialize comparator before setting it
+               ColumnDefinition firstCol = colDefs.get(0);
+               comparator.setColumn(firstCol.getPropertyType(),
+                               firstCol.getPropertyName());
+               viewer.setComparator(comparator);
+
+               return viewer;
+       }
+
+       private class CLProvider extends SimpleJcrNodeLabelProvider {
+
+               private static final long serialVersionUID = 1L;
+
+               public CLProvider(String propertyName) {
+                       super(propertyName);
+               }
+
+               public String getToolTipText(Object element) {
+                       return getText(element);
+               }
+
+               @Override
+               public Font getFont(Object elem) {
+                       // self
+                       String username = getProperty(elem, ARGEO_USER_ID);
+                       if (username.equals(session.getUserID()))
+                               return bold;
+
+                       // disabled
+                       try {
+                               Node userProfile = (Node) elem;
+                               // Node userProfile = userHome.getNode(ARGEO_PROFILE);
+                               if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean())
+                                       return italic;
+                               else
+                                       return null;
+                       } catch (RepositoryException e) {
+                               throw new ArgeoException("Cannot get font for " + username, e);
+                       }
+               }
+       }
+
+       @Override
+       public boolean setFocus() {
+               usersViewer.getTable().setFocus();
+               return true;
+       }
+
+       @Override
+       public void dispose() {
+               super.dispose();
+       }
+
+       public void refresh() {
+               refreshFilteredList();
+       }
+
+       private String getProperty(Object element, String name) {
+               try {
+                       Node userProfile = (Node) element;
+                       return userProfile.hasProperty(name) ? userProfile
+                                       .getProperty(name).getString() : "";
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot get property " + name, e);
+               }
+       }
+
+       private class UsersContentProvider implements IStructuredContentProvider {
+               private static final long serialVersionUID = 1L;
+
+               public Object[] getElements(Object inputElement) {
+                       return (Object[]) inputElement;
+               }
+
+               public void dispose() {
+               }
+
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+               }
+       }
+
+       /* MANAGE FILTER */
+       private void createFilterPart(Composite parent) {
+               // Text Area for the filter
+               filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH
+                               | SWT.ICON_CANCEL);
+               filterTxt.setMessage(FILTER_HELP_MSG);
+               filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
+                               | GridData.HORIZONTAL_ALIGN_FILL));
+               filterTxt.addModifyListener(new ModifyListener() {
+                       private static final long serialVersionUID = 1L;
+
+                       public void modifyText(ModifyEvent event) {
+                               refreshFilteredList();
+                       }
+               });
+       }
+
+       /**
+        * Refresh the user list: caller might overwrite in order to display a
+        * subset of all users, typically to remove current user from the list
+        */
+       protected void refreshFilteredList() {
+               List<Node> nodes;
+               try {
+                       nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session,
+                                       hasFilter ? filterTxt.getText() : null));
+                       usersViewer.setInput(nodes.toArray());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Unable to list users", e);
+               }
+       }
+
+       /**
+        * Build repository request : caller might overwrite in order to display a
+        * subset of all users
+        */
+       protected NodeIterator listFilteredElements(Session session, String filter)
+                       throws RepositoryException {
+               QueryManager queryManager = session.getWorkspace().getQueryManager();
+               QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+               Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE,
+                               ArgeoTypes.ARGEO_USER_PROFILE);
+
+               // Dynamically build constraint depending on the filter String
+               Constraint defaultC = null;
+               if (filter != null && !"".equals(filter.trim())) {
+                       String[] strs = filter.trim().split(" ");
+                       for (String token : strs) {
+                               StaticOperand so = factory.literal(session.getValueFactory()
+                                               .createValue("*" + token + "*"));
+                               Constraint currC = factory.fullTextSearch(
+                                               source.getSelectorName(), null, so);
+                               if (defaultC == null)
+                                       defaultC = currC;
+                               else
+                                       defaultC = factory.and(defaultC, currC);
+                       }
+               }
+
+               Ordering order = factory.ascending(factory.propertyValue(
+                               source.getSelectorName(), ARGEO_USER_ID));
+               Ordering[] orderings = { order };
+
+               QueryObjectModel query = factory.createQuery(source, defaultC,
+                               orderings, null);
+
+               QueryResult result = query.execute();
+               return result.getNodes();
+       }
+}
\ No newline at end of file
diff --git a/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java b/org.argeo.security.ui.admin/src/org/argeo/security/ui/admin/UserTableComposite.java
deleted file mode 100644 (file)
index 720fade..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-package org.argeo.security.ui.admin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.query.QueryManager;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.qom.Constraint;
-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 javax.jcr.query.qom.StaticOperand;
-
-import org.argeo.ArgeoException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.jcr.JcrUiUtils;
-import org.argeo.eclipse.ui.jcr.lists.ColumnDefinition;
-import org.argeo.eclipse.ui.jcr.lists.NodeViewerComparator;
-import org.argeo.eclipse.ui.jcr.lists.SimpleJcrNodeLabelProvider;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.argeo.eclipse.ui.utils.ViewerUtils;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.eclipse.jface.viewers.CheckboxTableViewer;
-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.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.Text;
-
-public class UserTableComposite extends Composite implements ArgeoNames {
-       // private final static Log log =
-       // LogFactory.getLog(UserTableComposite.class);
-
-       private static final long serialVersionUID = -7385959046279360420L;
-
-       private TableViewer usersViewer;
-       private Text filterTxt;
-       private final static String FILTER_HELP_MSG = "Type filter criterion "
-                       + "separated by a space";
-       private Session session;
-
-       private Font italic;
-       private Font bold;
-
-       private boolean hasFilter;
-       private boolean hasSelectionColumn;
-
-       // private List<Node> selectedItems = new ArrayList<Node>();
-
-       /**
-        * Overwrite to display other columns
-        */
-       public List<ColumnDefinition> getColumnsDef() {
-               List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
-
-               // User ID
-               columnDefs.add(new ColumnDefinition(null, ARGEO_USER_ID,
-                               PropertyType.STRING, "User ID", 100));
-               // Displayed name
-               columnDefs.add(new ColumnDefinition(null, Property.JCR_TITLE,
-                               PropertyType.STRING, "Name", 150));
-
-               // E-mail
-               columnDefs.add(new ColumnDefinition(null, ARGEO_PRIMARY_EMAIL,
-                               PropertyType.STRING, "E-mail", 150));
-
-               // Description
-               columnDefs.add(new ColumnDefinition(null, Property.JCR_DESCRIPTION,
-                               PropertyType.STRING, "Description", 200));
-
-               return columnDefs;
-       }
-
-       public UserTableComposite(Composite parent, int style, Session session) {
-               super(parent, style);
-               this.session = session;
-       }
-
-       /**
-        * 
-        * @param addFilter
-        *            choose to add a field to filter results or not
-        * @param addSelection
-        *            choose to add a column to select some of the displayed results
-        *            or not
-        */
-       public void populate(boolean addFilter, boolean addSelection) {
-               // initialization
-               Composite parent = this;
-               italic = EclipseUiUtils.getItalicFont(parent);
-               bold = EclipseUiUtils.getBoldFont(parent);
-               hasFilter = addFilter;
-               hasSelectionColumn = addSelection;
-
-               // Main Layout
-               this.setLayout(new GridLayout(1, false));
-               if (hasFilter)
-                       createFilterPart(parent);
-               usersViewer = createTableViewer(parent);
-               EclipseUiSpecificUtils.enableToolTipSupport(usersViewer);
-               usersViewer.setContentProvider(new UsersContentProvider());
-               refreshFilteredList();
-       }
-
-       public List<Node> getSelectedUsers() {
-               if (hasSelectionColumn) {
-                       Object[] elements = ((CheckboxTableViewer) usersViewer)
-                                       .getCheckedElements();
-
-                       List<Node> result = new ArrayList<Node>();
-                       for (Object obj : elements) {
-                               result.add((Node) obj);
-                       }
-                       return result;
-               } else
-                       throw new ArgeoException("Unvalid request: no selection column "
-                                       + "has been created for the current table");
-       }
-
-       /** Returns the User table viewer, typically to add doubleclick listener */
-       public TableViewer getTableViewer() {
-               return usersViewer;
-       }
-       
-       /** Returns filter String or null*/
-       protected String getFilterString() {
-               return hasFilter ? filterTxt.getText() : null;
-       }
-       
-       
-
-       private TableViewer createTableViewer(final Composite parent) {
-               int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
-               if (hasSelectionColumn)
-                       style = style | SWT.CHECK;
-
-               Table table = new Table(parent, style);
-               table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
-               TableViewer viewer;
-               if (hasSelectionColumn)
-                       viewer = new CheckboxTableViewer(table);
-               else
-                       viewer = new TableViewer(table);
-               table.setLinesVisible(true);
-               table.setHeaderVisible(true);
-
-               // pass a mapping between col index and property name to the comparator.
-               // List<String> propertiesList = new ArrayList<String>();
-
-               TableViewerColumn column;
-               int offset = 0;
-               if (hasSelectionColumn) {
-                       offset = 1;
-                       column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE,
-                                       25);
-                       column.setLabelProvider(new ColumnLabelProvider() {
-                               private static final long serialVersionUID = 1L;
-
-                               @Override
-                               public String getText(Object element) {
-                                       return null;
-                               }
-                       });
-                       SelectionAdapter selectionAdapter = new SelectionAdapter() {
-                               private static final long serialVersionUID = 1L;
-
-                               boolean allSelected = false;
-
-                               @Override
-                               public void widgetSelected(SelectionEvent e) {
-                                       allSelected = !allSelected;
-                                       ((CheckboxTableViewer) usersViewer)
-                                                       .setAllChecked(allSelected);
-                               }
-                       };
-                       column.getColumn().addSelectionListener(selectionAdapter);
-               }
-
-               // Create other columns
-               List<ColumnDefinition> colDefs = getColumnsDef();
-
-               NodeViewerComparator comparator = new NodeViewerComparator();
-               int i = offset;
-               for (ColumnDefinition colDef : colDefs) {
-                       column = ViewerUtils.createTableViewerColumn(viewer,
-                                       colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
-                       column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
-                       column.getColumn().addSelectionListener(
-                                       JcrUiUtils.getNodeSelectionAdapter(i,
-                                                       colDef.getPropertyType(), colDef.getPropertyName(),
-                                                       comparator, viewer));
-                       i++;
-               }
-
-               // IMPORTANT: initialize comparator before setting it
-               ColumnDefinition firstCol = colDefs.get(0);
-               comparator.setColumn(firstCol.getPropertyType(),
-                               firstCol.getPropertyName());
-               viewer.setComparator(comparator);
-
-               return viewer;
-       }
-
-       private class CLProvider extends SimpleJcrNodeLabelProvider {
-
-               private static final long serialVersionUID = 1L;
-
-               public CLProvider(String propertyName) {
-                       super(propertyName);
-               }
-
-               public String getToolTipText(Object element) {
-                       return getText(element);
-               }
-
-               @Override
-               public Font getFont(Object elem) {
-                       // self
-                       String username = getProperty(elem, ARGEO_USER_ID);
-                       if (username.equals(session.getUserID()))
-                               return bold;
-
-                       // disabled
-                       try {
-                               Node userProfile = (Node) elem;
-                               // Node userProfile = userHome.getNode(ARGEO_PROFILE);
-                               if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean())
-                                       return italic;
-                               else
-                                       return null;
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot get font for " + username, e);
-                       }
-               }
-       }
-
-       @Override
-       public boolean setFocus() {
-               usersViewer.getTable().setFocus();
-               return true;
-       }
-
-       @Override
-       public void dispose() {
-               super.dispose();
-       }
-
-       public void refresh() {
-               refreshFilteredList();
-       }
-
-       private String getProperty(Object element, String name) {
-               try {
-                       Node userProfile = (Node) element;
-                       return userProfile.hasProperty(name) ? userProfile
-                                       .getProperty(name).getString() : "";
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot get property " + name, e);
-               }
-       }
-
-       private class UsersContentProvider implements IStructuredContentProvider {
-               private static final long serialVersionUID = 1L;
-
-               public Object[] getElements(Object inputElement) {
-                       return (Object[]) inputElement;
-               }
-
-               public void dispose() {
-               }
-
-               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-               }
-       }
-
-       /* MANAGE FILTER */
-       private void createFilterPart(Composite parent) {
-               // Text Area for the filter
-               filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH
-                               | SWT.ICON_CANCEL);
-               filterTxt.setMessage(FILTER_HELP_MSG);
-               filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
-                               | GridData.HORIZONTAL_ALIGN_FILL));
-               filterTxt.addModifyListener(new ModifyListener() {
-                       private static final long serialVersionUID = 1L;
-
-                       public void modifyText(ModifyEvent event) {
-                               refreshFilteredList();
-                       }
-               });
-       }
-
-       /**
-        * Refresh the user list: caller might overwrite in order to display a
-        * subset of all users, typically to remove current user from the list
-        */
-       protected void refreshFilteredList() {
-               List<Node> nodes;
-               try {
-                       nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session,
-                                       hasFilter ? filterTxt.getText() : null));
-                       usersViewer.setInput(nodes.toArray());
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Unable to list users", e);
-               }
-       }
-
-       /**
-        * Build repository request : caller might overwrite in order to display a
-        * subset of all users
-        */
-       protected NodeIterator listFilteredElements(Session session, String filter)
-                       throws RepositoryException {
-               QueryManager queryManager = session.getWorkspace().getQueryManager();
-               QueryObjectModelFactory factory = queryManager.getQOMFactory();
-
-               Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE,
-                               ArgeoTypes.ARGEO_USER_PROFILE);
-
-               // Dynamically build constraint depending on the filter String
-               Constraint defaultC = null;
-               if (filter != null && !"".equals(filter.trim())) {
-                       String[] strs = filter.trim().split(" ");
-                       for (String token : strs) {
-                               StaticOperand so = factory.literal(session.getValueFactory()
-                                               .createValue("*" + token + "*"));
-                               Constraint currC = factory.fullTextSearch(
-                                               source.getSelectorName(), null, so);
-                               if (defaultC == null)
-                                       defaultC = currC;
-                               else
-                                       defaultC = factory.and(defaultC, currC);
-                       }
-               }
-
-               Ordering order = factory.ascending(factory.propertyValue(
-                               source.getSelectorName(), ARGEO_USER_ID));
-               Ordering[] orderings = { order };
-
-               QueryObjectModel query = factory.createQuery(source, defaultC,
-                               orderings, null);
-
-               QueryResult result = query.execute();
-               return result.getNodes();
-       }
-}
\ No newline at end of file
index 0afc409bb78b26ecc7eaf77befea1c0fe6e1ad82..ac979240183a07825c56be5e7dd91b746cd5f5a5 100644 (file)
@@ -24,13 +24,13 @@ import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
 
 import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.parts.UsersTable;
 import org.argeo.eclipse.ui.workbench.CommandUtils;
 import org.argeo.jcr.ArgeoJcrConstants;
 import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.ArgeoTypes;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.UserTableComposite;
 import org.argeo.security.ui.admin.commands.OpenArgeoUserEditor;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
@@ -49,7 +49,7 @@ public class UsersView extends ViewPart implements ArgeoNames {
        /* DEPENDENCY INJECTION */
        private Session session;
 
-       private UserTableComposite userTableCmp;
+       private UsersTable userTableCmp;
        private JcrUserListener userStructureListener;
        private JcrUserListener userPropertiesListener;
 
@@ -58,7 +58,7 @@ public class UsersView extends ViewPart implements ArgeoNames {
                parent.setLayout(new FillLayout());
 
                // Create the composite that displays the list and a filter
-               userTableCmp = new UserTableComposite(parent, SWT.NO_FOCUS, session);
+               userTableCmp = new UsersTable(parent, SWT.NO_FOCUS, session);
                userTableCmp.populate(true, false);
 
                // Configure
index 71e4a1b734df17147c4023db823a6e1783a9c594..0cf3c49e35a3f9c037e63b1368fbf22e46ce104f 100644 (file)
@@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.argeo.ArgeoMonitor;
 import org.argeo.eclipse.ui.EclipseArgeoMonitor;
+import org.argeo.eclipse.ui.parts.UsersTable;
 import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.security.UserAdminService;
@@ -38,7 +39,6 @@ import org.argeo.security.jcr.JcrSecurityModel;
 import org.argeo.security.jcr.JcrUserDetails;
 import org.argeo.security.ui.PrivilegedJob;
 import org.argeo.security.ui.admin.SecurityAdminPlugin;
-import org.argeo.security.ui.admin.UserTableComposite;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
@@ -465,7 +465,7 @@ public class UserBatchUpdateWizard extends Wizard {
        private class ChooseUsersWizardPage extends WizardPage implements
                        IPageChangedListener {
                private static final long serialVersionUID = 1L;
-               private UserTableComposite userTableCmp;
+               private UsersTable userTableCmp;
                private Composite container;
                private Session session;
 
@@ -504,7 +504,7 @@ public class UserBatchUpdateWizard extends Wizard {
                        return userTableCmp.getSelectedUsers();
                }
 
-               private class MyUserTableCmp extends UserTableComposite {
+               private class MyUserTableCmp extends UsersTable {
 
                        private static final long serialVersionUID = 1L;
 
@@ -542,7 +542,7 @@ public class UserBatchUpdateWizard extends Wizard {
        private class ValidateAndLaunchWizardPage extends WizardPage implements
                        IPageChangedListener {
                private static final long serialVersionUID = 1L;
-               private UserTableComposite userTableCmp;
+               private UsersTable userTableCmp;
                private Session session;
 
                public ValidateAndLaunchWizardPage(Session session) {
@@ -562,7 +562,7 @@ public class UserBatchUpdateWizard extends Wizard {
                                ((IPageChangeProvider) container).addPageChangedListener(this);
                        }
 
-                       userTableCmp = new UserTableComposite(mainCmp, SWT.NO_FOCUS,
+                       userTableCmp = new UsersTable(mainCmp, SWT.NO_FOCUS,
                                        session);
                        userTableCmp.populate(false, false);
                        setControl(mainCmp);