Fix bug 28 ( https://www.argeo.org/bugzilla/show_bug.cgi?id=28 )
authorBruno Sinou <bsinou@argeo.org>
Wed, 20 Mar 2013 12:33:12 +0000 (12:33 +0000)
committerBruno Sinou <bsinou@argeo.org>
Wed, 20 Mar 2013 12:33:12 +0000 (12:33 +0000)
+ Add sorting and filtering to the user view
+ some cleanings: remove hard-coded plugin ID, factorize command call

git-svn-id: https://svn.argeo.org/commons/trunk@6180 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java

index 8246918311bffe0c442068c9fea99f4efa093b70..41d8ed036bae2cb18a17246f8b9b7c899efca8ad 100644 (file)
@@ -26,21 +26,26 @@ import javax.jcr.Session;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 import javax.jcr.observation.EventListener;
-import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Constraint;
+import javax.jcr.query.qom.DynamicOperand;
+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.specific.EclipseUiSpecificUtils;
+import org.argeo.eclipse.ui.utils.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.commands.OpenArgeoUserEditor;
-import org.eclipse.core.commands.Command;
-import org.eclipse.core.commands.IParameter;
-import org.eclipse.core.commands.Parameterization;
-import org.eclipse.core.commands.ParameterizedCommand;
 import org.eclipse.jface.viewers.ColumnLabelProvider;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
@@ -49,21 +54,35 @@ import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.jface.viewers.TableViewerColumn;
 import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
 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.events.SelectionListener;
 import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Table;
-import org.eclipse.ui.IWorkbench;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.commands.ICommandService;
-import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.part.ViewPart;
 
 /** List all users. */
 public class UsersView extends ViewPart implements ArgeoNames {
-       public final static String ID = "org.argeo.security.ui.admin.adminUsersView";
+       public final static String ID = SecurityAdminPlugin.PLUGIN_ID
+                       + ".adminUsersView";
 
        private TableViewer viewer;
+       private Text filterTxt;
+       private final static String FILTER_HELP_MSG = "Enter filter criterion "
+                       + "separated by a space (on user ID, name and E-mail";
+       private final static Image FILTER_RESET = SecurityAdminPlugin
+                       .getImageDescriptor("icons/users.gif").createImage();
+
        private Session session;
 
        private UserStructureListener userStructureListener;
@@ -77,14 +96,16 @@ public class UsersView extends ViewPart implements ArgeoNames {
                italic = EclipseUiUtils.getItalicFont(parent);
                bold = EclipseUiUtils.getBoldFont(parent);
 
-               // viewer = new TableViewer(createTable(parent));
+               // Main Layout
+               GridLayout layout = new GridLayout(1, false);
+               parent.setLayout(layout);
+               createFilterPart(parent);
+
                viewer = createTableViewer(parent);
                EclipseUiSpecificUtils.enableToolTipSupport(viewer);
                viewer.setContentProvider(new UsersContentProvider());
-               // viewer.setLabelProvider(new UsersLabelProvider());
                viewer.addDoubleClickListener(new ViewDoubleClickListener());
                getViewSite().setSelectionProvider(viewer);
-               viewer.setInput(getViewSite());
 
                userStructureListener = new UserStructureListener();
                JcrUtils.addListener(session, userStructureListener, Event.NODE_ADDED
@@ -95,6 +116,8 @@ public class UsersView extends ViewPart implements ArgeoNames {
                                                | Event.PROPERTY_REMOVED,
                                ArgeoJcrConstants.PEOPLE_BASE_PATH,
                                ArgeoTypes.ARGEO_USER_PROFILE);
+
+               refreshFilteredList();
        }
 
        protected TableViewer createTableViewer(final Composite parent) {
@@ -104,10 +127,15 @@ public class UsersView extends ViewPart implements ArgeoNames {
                table.setLinesVisible(true);
                table.setHeaderVisible(true);
 
+               // pass a mapping between col index and property name to the comparator.
+               List<String> propertiesList = new ArrayList<String>();
+
                // User ID
                TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
                column.getColumn().setText("User ID");
                column.getColumn().setWidth(100);
+               column.getColumn().addSelectionListener(getSelectionAdapter(0));
+               propertiesList.add(ARGEO_USER_ID);
                column.setLabelProvider(new CLProvider() {
                        public String getText(Object elem) {
                                return getProperty(elem, ARGEO_USER_ID);
@@ -122,6 +150,8 @@ public class UsersView extends ViewPart implements ArgeoNames {
                column = new TableViewerColumn(viewer, SWT.NONE);
                column.getColumn().setText("Name");
                column.getColumn().setWidth(150);
+               column.getColumn().addSelectionListener(getSelectionAdapter(1));
+               propertiesList.add(Property.JCR_TITLE);
                column.setLabelProvider(new CLProvider() {
                        public String getText(Object elem) {
                                return getProperty(elem, Property.JCR_TITLE);
@@ -132,22 +162,28 @@ public class UsersView extends ViewPart implements ArgeoNames {
                column = new TableViewerColumn(viewer, SWT.NONE);
                column.getColumn().setText("E-mail");
                column.getColumn().setWidth(150);
+               column.getColumn().addSelectionListener(getSelectionAdapter(2));
+               propertiesList.add(ARGEO_PRIMARY_EMAIL);
                column.setLabelProvider(new CLProvider() {
                        public String getText(Object elem) {
                                return getProperty(elem, ARGEO_PRIMARY_EMAIL);
                        }
                });
 
-               // E-mail
+               // Description
                column = new TableViewerColumn(viewer, SWT.NONE);
                column.getColumn().setText("Description");
                column.getColumn().setWidth(200);
+               column.getColumn().addSelectionListener(getSelectionAdapter(3));
+               propertiesList.add(Property.JCR_DESCRIPTION);
                column.setLabelProvider(new CLProvider() {
                        public String getText(Object elem) {
                                return getProperty(elem, Property.JCR_DESCRIPTION);
                        }
                });
 
+               viewer.setComparator(new UsersViewerComparator(propertiesList));
+
                return viewer;
        }
 
@@ -179,6 +215,85 @@ public class UsersView extends ViewPart implements ArgeoNames {
 
        }
 
+       private SelectionAdapter getSelectionAdapter(final int index) {
+               SelectionAdapter selectionAdapter = new SelectionAdapter() {
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               UsersViewerComparator comparator = (UsersViewerComparator) viewer
+                                               .getComparator();
+
+                               if (index == comparator.getSortColumn()) {
+                                       comparator.setAscending(!comparator.isAscending());
+                               }
+                               comparator.setSortColumn(index);
+                               viewer.getTable().setSortColumn(
+                                               viewer.getTable().getColumn(index));
+                               viewer.getTable().setSortDirection(
+                                               comparator.isAscending() ? SWT.UP : SWT.DOWN);
+                               viewer.refresh(false);
+                       }
+               };
+               return selectionAdapter;
+       }
+
+       private class UsersViewerComparator extends ViewerComparator {
+
+               private List<String> propertyList;
+               private int sortColumn = 0;
+               private boolean ascending = true;
+               // use this to enable two levels sort
+               @SuppressWarnings("unused")
+               private int lastSortColumn = 0;
+               @SuppressWarnings("unused")
+               private boolean lastAscending = true;
+
+               public UsersViewerComparator(List<String> propertyList) {
+                       super();
+                       this.propertyList = propertyList;
+               }
+
+               public int compare(Viewer viewer, Object e1, Object e2) {
+                       String s1 = getProperty(e1, propertyList.get(sortColumn));
+                       String s2 = getProperty(e2, propertyList.get(sortColumn));
+                       int result = super.compare(viewer, s1, s2);
+                       return ascending ? result : (-1) * result;
+               }
+
+               /**
+                * @return Returns the sortColumn.
+                */
+               public int getSortColumn() {
+                       return sortColumn;
+               }
+
+               /**
+                * @param sortColumn
+                *            The sortColumn to set.
+                */
+               public void setSortColumn(int sortColumn) {
+                       if (this.sortColumn != sortColumn) {
+                               lastSortColumn = this.sortColumn;
+                               lastAscending = this.ascending;
+                               this.sortColumn = sortColumn;
+                       }
+               }
+
+               /**
+                * @return Returns the ascending.
+                */
+               public boolean isAscending() {
+                       return ascending;
+               }
+
+               /**
+                * @param ascending
+                *            The ascending to set.
+                */
+               public void setAscending(boolean ascending) {
+                       this.ascending = ascending;
+               }
+       }
+
        @Override
        public void setFocus() {
                viewer.getTable().setFocus();
@@ -235,24 +350,26 @@ public class UsersView extends ViewPart implements ArgeoNames {
        private class UsersContentProvider implements IStructuredContentProvider {
 
                public Object[] getElements(Object inputElement) {
-                       try {
-                               Query query = session
-                                               .getWorkspace()
-                                               .getQueryManager()
-                                               .createQuery(
-                                                               "select * from ["
-                                                                               + ArgeoTypes.ARGEO_USER_PROFILE + "]",
-                                                               Query.JCR_SQL2);
-                               NodeIterator nit = query.execute().getNodes();
-                               List<Node> userProfiles = new ArrayList<Node>();
-                               while (nit.hasNext()) {
-                                       userProfiles.add(nit.nextNode());
-                               }
-                               return userProfiles.toArray();
-                       } catch (RepositoryException e) {
-                               throw new ArgeoException("Cannot list users", e);
-                       }
-                       // return userAdminService.listUsers().toArray();
+                       return (Object[]) inputElement;
+
+                       // try {
+                       // Query query = session
+                       // .getWorkspace()
+                       // .getQueryManager()
+                       // .createQuery(
+                       // "select * from ["
+                       // + ArgeoTypes.ARGEO_USER_PROFILE + "]",
+                       // Query.JCR_SQL2);
+                       // NodeIterator nit = query.execute().getNodes();
+                       // List<Node> userProfiles = new ArrayList<Node>();
+                       // while (nit.hasNext()) {
+                       // userProfiles.add(nit.nextNode());
+                       // }
+                       // return userProfiles.toArray();
+                       // } catch (RepositoryException e) {
+                       // throw new ArgeoException("Cannot list users", e);
+                       // }
+                       // // return userAdminService.listUsers().toArray();
                }
 
                public void dispose() {
@@ -271,38 +388,121 @@ public class UsersView extends ViewPart implements ArgeoNames {
                        Object obj = ((IStructuredSelection) evt.getSelection())
                                        .getFirstElement();
                        if (obj instanceof Node) {
-                               IWorkbench iw = SecurityAdminPlugin.getDefault().getWorkbench();
-                               IHandlerService handlerService = (IHandlerService) iw
-                                               .getService(IHandlerService.class);
                                try {
                                        String username = ((Node) obj).getProperty(ARGEO_USER_ID)
                                                        .getString();
                                        String commandId = OpenArgeoUserEditor.COMMAND_ID;
                                        String paramName = OpenArgeoUserEditor.PARAM_USERNAME;
-
-                                       // TODO: factorize this
-                                       // execute related command
-                                       IWorkbenchWindow window = iw.getActiveWorkbenchWindow();
-                                       ICommandService cmdService = (ICommandService) window
-                                                       .getService(ICommandService.class);
-                                       Command cmd = cmdService.getCommand(commandId);
-                                       ArrayList<Parameterization> parameters = new ArrayList<Parameterization>();
-                                       IParameter iparam = cmd.getParameter(paramName);
-                                       Parameterization param = new Parameterization(iparam,
-                                                       username);
-                                       parameters.add(param);
-                                       ParameterizedCommand pc = new ParameterizedCommand(cmd,
-                                                       parameters.toArray(new Parameterization[parameters
-                                                                       .size()]));
-                                       handlerService = (IHandlerService) window
-                                                       .getService(IHandlerService.class);
-                                       handlerService.executeCommand(pc, null);
-                               } catch (Exception e) {
-                                       throw new ArgeoException("Cannot open editor", e);
+                                       CommandUtils.callCommand(commandId, paramName, username);
+                               } catch (RepositoryException e) {
+                                       throw new ArgeoException("Cannot open user editor", e);
                                }
+                       }
+               }
+       }
 
+       /* MANAGE FILTER */
+       private void createFilterPart(Composite parent) {
+               Composite header = new Composite(parent, SWT.FILL);
+               header.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               header.setLayout(new GridLayout(2, false));
+
+               // Text Area to filter
+               filterTxt = new Text(header, SWT.BORDER | SWT.SINGLE);
+               filterTxt.setMessage(FILTER_HELP_MSG);
+               GridData gd = new GridData(SWT.FILL, SWT.FILL, false, false);
+               gd.grabExcessHorizontalSpace = true;
+               filterTxt.setLayoutData(gd);
+               filterTxt.addModifyListener(new ModifyListener() {
+                       public void modifyText(ModifyEvent event) {
+                               refreshFilteredList();
                        }
+               });
+
+               Button resetBtn = new Button(header, SWT.PUSH);
+               resetBtn.setImage(FILTER_RESET);
+               resetBtn.addSelectionListener(new SelectionListener() {
+                       public void widgetSelected(SelectionEvent e) {
+                               resetFilter();
+                       }
+
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                       }
+               });
+
+       }
+
+       private void resetFilter() {
+               filterTxt.setText("");
+               filterTxt.setMessage(FILTER_HELP_MSG);
+       }
+
+       private void refreshFilteredList() {
+               List<Node> nodes;
+               try {
+                       nodes = JcrUtils.nodeIteratorToList(listFilteredElements(session,
+                                       filterTxt.getText()));
+                       viewer.setInput(nodes.toArray());
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Unable to list users", e);
                }
        }
 
-}
+       /** Build repository request */
+       private NodeIterator listFilteredElements(Session session, String filter)
+                       throws RepositoryException {
+               QueryManager queryManager = session.getWorkspace().getQueryManager();
+               QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+               final String bundleArtifactsSelector = "userProfiles";
+               Selector source = factory.selector(ArgeoTypes.ARGEO_USER_PROFILE,
+                               bundleArtifactsSelector);
+
+               // Create a dynamic operand for each property on which we want to filter
+               DynamicOperand userIdDO = factory.propertyValue(
+                               source.getSelectorName(), ARGEO_USER_ID);
+               DynamicOperand fullNameDO = factory.propertyValue(
+                               source.getSelectorName(), Property.JCR_TITLE);
+               DynamicOperand mailDO = factory.propertyValue(source.getSelectorName(),
+                               ARGEO_PRIMARY_EMAIL);
+
+               // Default Constraint: no source artifacts
+               Constraint defaultC = null;
+
+               // Build constraints based the textArea content
+               if (filter != null && !"".equals(filter.trim())) {
+                       // Parse the String
+                       String[] strs = filter.trim().split(" ");
+                       for (String token : strs) {
+                               token = token.replace('*', '%');
+                               StaticOperand so = factory.literal(session.getValueFactory()
+                                               .createValue("%" + token + "%"));
+
+                               Constraint currC = factory.comparison(userIdDO,
+                                               QueryObjectModelFactory.JCR_OPERATOR_LIKE, so);
+                               currC = factory.or(currC, factory.comparison(fullNameDO,
+                                               QueryObjectModelFactory.JCR_OPERATOR_LIKE, so));
+                               currC = factory.or(currC, factory.comparison(mailDO,
+                                               QueryObjectModelFactory.JCR_OPERATOR_LIKE, so));
+
+                               if (defaultC == null)
+                                       defaultC = currC;
+                               else
+                                       defaultC = factory.and(defaultC, currC);
+                       }
+               }
+
+               Ordering order = factory.descending(factory.propertyValue(
+                               bundleArtifactsSelector, ARGEO_USER_ID));
+               // Ordering order2 = factory.ascending(factory.propertyValue(
+               // bundleArtifactsSelector, ARGEO_PRIMARY_EMAIL));
+               // Ordering[] orderings = { order, order2 };
+               Ordering[] orderings = { order };
+
+               QueryObjectModel query = factory.createQuery(source, defaultC,
+                               orderings, null);
+
+               QueryResult result = query.execute();
+               return result.getNodes();
+       }
+}
\ No newline at end of file