From 0a89a0f07d991767c881092d2809ccef93c60362 Mon Sep 17 00:00:00 2001 From: Bruno Sinou Date: Wed, 20 Mar 2013 20:58:22 +0000 Subject: [PATCH] Merge Add sorting to user list table https://www.argeo.org/bugzilla/show_bug.cgi?id=28 git-svn-id: https://svn.argeo.org/commons/branches/1.x@6183 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../security/ui/admin/views/UsersView.java | 312 ++++++++++++++---- 1 file changed, 256 insertions(+), 56 deletions(-) diff --git a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java index 824691831..41d8ed036 100644 --- a/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java +++ b/security/plugins/org.argeo.security.ui.admin/src/main/java/org/argeo/security/ui/admin/views/UsersView.java @@ -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 propertiesList = new ArrayList(); + // 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 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 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 userProfiles = new ArrayList(); - 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 userProfiles = new ArrayList(); + // 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 parameters = new ArrayList(); - 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 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 -- 2.30.2