From a94f5f0bffe179ba66de6126a90c0b7db4c0f3d2 Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Wed, 11 Mar 2009 19:51:09 +0000 Subject: [PATCH] Merged V3.1 to HEAD 13249: Fix for ETHREEOH-1064 and ETHREEOH-1286 and fix for issue where New Page action not activated in Share Wiki page list. 13251: Final part of fix for ETHREEOH-1270 - Group pickers in JSF client now use new findAuthorities() API to find groups for user searches - over 10x quicker for installations with many groups. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13580 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 1 + config/alfresco/web-client-config.xml | 3 + .../web/bean/groups/AddUsersDialog.java | 9 +-- .../web/bean/wcm/SetPermissionsDialog.java | 27 ++++---- .../bean/wizard/BaseInviteUsersWizard.java | 61 +++++++++++-------- .../web/bean/workflow/BaseReassignDialog.java | 40 ++++++++---- .../web/config/ClientConfigElement.java | 22 +++++++ .../web/config/ClientElementReader.java | 8 +++ .../org/alfresco/web/ui/common/Utils.java | 19 ++++++ 9 files changed, 130 insertions(+), 60 deletions(-) diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 7966b16c99..dc1cc201cf 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -306,6 +306,7 @@ upload_new_version=Upload new version checkin_this_file=Check in this file cannot_delete_node_has_working_copy=Cannot delete file \"{0}\" as it has an associated working copy. unknown=Unknown +picker_search_min=Please enter at least {0} characters to perform a search. # Properties username=User Name diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 3aeeabac79..cb44f6f465 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -111,6 +111,9 @@ true + + + 2 diff --git a/source/java/org/alfresco/web/bean/groups/AddUsersDialog.java b/source/java/org/alfresco/web/bean/groups/AddUsersDialog.java index 988ddf8237..9ecef34fc1 100644 --- a/source/java/org/alfresco/web/bean/groups/AddUsersDialog.java +++ b/source/java/org/alfresco/web/bean/groups/AddUsersDialog.java @@ -46,7 +46,6 @@ import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.BaseDialogBean; import org.alfresco.web.bean.groups.GroupsDialog.UserAuthorityDetails; @@ -213,13 +212,7 @@ public class AddUsersDialog extends BaseDialogBean // Use lucene search to retrieve user details String term = QueryParser.escape(contains.trim()); StringBuilder query = new StringBuilder(128); - query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:"); - query.append(term); - query.append("*"); + Utils.generatePersonSearch(query, term); List nodes; ResultSet resultSet = Repository.getServiceRegistry(context).getSearchService().query( Repository.getStoreRef(), diff --git a/source/java/org/alfresco/web/bean/wcm/SetPermissionsDialog.java b/source/java/org/alfresco/web/bean/wcm/SetPermissionsDialog.java index 163dc6cd6c..ec8a638d1f 100644 --- a/source/java/org/alfresco/web/bean/wcm/SetPermissionsDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/SetPermissionsDialog.java @@ -39,7 +39,6 @@ import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.ui.common.SortableSelectItem; @@ -55,7 +54,6 @@ import org.apache.commons.logging.LogFactory; */ public class SetPermissionsDialog extends UpdatePermissionsDialog { - private static final long serialVersionUID = -8139619811033232880L; /** logger */ @@ -251,13 +249,7 @@ public class SetPermissionsDialog extends UpdatePermissionsDialog // Use lucene search to retrieve user details String term = QueryParser.escape(contains.trim()); StringBuilder query = new StringBuilder(128); - query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:"); - query.append(term); - query.append("*"); + Utils.generatePersonSearch(query, term); ResultSet resultSet = Repository.getServiceRegistry(context).getSearchService().query(Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString()); List nodes; try @@ -284,18 +276,23 @@ public class SetPermissionsDialog extends UpdatePermissionsDialog } else { - // groups - simple text based match on name - Set groups = getAuthorityService().getAllAuthorities(AuthorityType.GROUP); + // groups - text search match on supplied name + String term = PermissionService.GROUP_PREFIX + "*" + contains.trim() + "*"; + Set groups; + groups = getAuthorityService().findAuthorities(AuthorityType.GROUP, term); groups.addAll(getAuthorityService().getAllAuthorities(AuthorityType.EVERYONE)); - String containsLower = contains.trim().toLowerCase(); - int offset = PermissionService.GROUP_PREFIX.length(); + String groupDisplayName; for (String group : groups) { - if (group.toLowerCase().indexOf(containsLower, offset) != -1) + // get display name, if not present strip prefix from group id + groupDisplayName = getAuthorityService().getAuthorityDisplayName(group); + if (groupDisplayName == null || groupDisplayName.length() == 0) { - results.add(new SortableSelectItem(group, group.substring(offset), group)); + groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length()); } + + results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName)); } } diff --git a/source/java/org/alfresco/web/bean/wizard/BaseInviteUsersWizard.java b/source/java/org/alfresco/web/bean/wizard/BaseInviteUsersWizard.java index 39e2390310..463947643f 100644 --- a/source/java/org/alfresco/web/bean/wizard/BaseInviteUsersWizard.java +++ b/source/java/org/alfresco/web/bean/wizard/BaseInviteUsersWizard.java @@ -35,6 +35,7 @@ import java.util.Map; import java.util.ResourceBundle; import java.util.Set; +import javax.faces.application.FacesMessage; import javax.faces.component.UISelectOne; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; @@ -86,6 +87,7 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean private static final String MSG_INVITED_TO = "invited_to"; private static final String MSG_INVITED_ROLE = "invite_role"; private static final String MSG_MAX_USERS = "max_users_returned"; + private static final String MSG_SEARCH_MINIMUM = "picker_search_min"; protected static final String STEP_NOTIFY = "notify"; @@ -365,6 +367,15 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean { FacesContext context = FacesContext.getCurrentInstance(); + // quick exit if not enough characters entered for a search + String search = contains.trim(); + int searchMin = Application.getClientConfig(context).getPickerSearchMinimum(); + if (search.length() < searchMin) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage(context, MSG_SEARCH_MINIMUM), searchMin)); + return new SelectItem[0]; + } + SelectItem[] items; this.maxUsersReturned = false; @@ -374,12 +385,14 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean tx = Repository.getUserTransaction(context, true); tx.begin(); - List results = new ArrayList(); + int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults(); + + List results; if (filterIndex == 0) { // Use lucene search to retrieve user details - String term = QueryParser.escape(contains.trim()); + String term = QueryParser.escape(search); StringBuilder query = new StringBuilder(128); if (contains == null || contains.length() == 0) { @@ -390,17 +403,9 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean } else { - query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:"); - query.append(term); - query.append("*"); + Utils.generatePersonSearch(query, term); } - int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults(); - if (logger.isDebugEnabled()) { logger.debug("Maximum invite users results size: " + maxResults); @@ -428,12 +433,7 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean resultSet.close(); } - // set the maximum users returned flag if appropriate - if (nodes.size() == maxResults) - { - this.maxUsersReturned = true; - } - + results = new ArrayList(nodes.size()); for (int index=0; index groups = getAuthorityService().getAllAuthorities(AuthorityType.GROUP); + // groups - text search match on supplied name + String term = PermissionService.GROUP_PREFIX + "*" + search + "*"; + Set groups; + groups = getAuthorityService().findAuthorities(AuthorityType.GROUP, term); groups.addAll(getAuthorityService().getAllAuthorities(AuthorityType.EVERYONE)); - - String containsLower = contains.trim().toLowerCase(); + + results = new ArrayList(groups.size()); + + int count = 0; String groupDisplayName; for (String group : groups) { // get display name, if not present strip prefix from group id - groupDisplayName = authorityService.getAuthorityDisplayName(group); + groupDisplayName = getAuthorityService().getAuthorityDisplayName(group); if (groupDisplayName == null || groupDisplayName.length() == 0) { groupDisplayName = group.substring(PermissionService.GROUP_PREFIX.length()); } - if (groupDisplayName.toLowerCase().indexOf(containsLower) != -1) - { - results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName)); - } + results.add(new SortableSelectItem(group, groupDisplayName, groupDisplayName)); + + if (++count == maxResults) break; } } @@ -475,6 +478,12 @@ public abstract class BaseInviteUsersWizard extends BaseWizardBean results.toArray(items); Arrays.sort(items); + // set the maximum users returned flag if appropriate + if (results.size() == maxResults) + { + this.maxUsersReturned = true; + } + // commit the transaction tx.commit(); } diff --git a/source/java/org/alfresco/web/bean/workflow/BaseReassignDialog.java b/source/java/org/alfresco/web/bean/workflow/BaseReassignDialog.java index b1d18d987c..252f7a9f6d 100644 --- a/source/java/org/alfresco/web/bean/workflow/BaseReassignDialog.java +++ b/source/java/org/alfresco/web/bean/workflow/BaseReassignDialog.java @@ -37,12 +37,13 @@ import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.search.impl.lucene.QueryParser; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.BaseDialogBean; import org.alfresco.web.bean.repository.Repository; @@ -57,6 +58,8 @@ import org.alfresco.web.ui.common.Utils; */ public abstract class BaseReassignDialog extends BaseDialogBean { + private static final String MSG_SEARCH_MINIMUM = "picker_search_min"; + transient private WorkflowService workflowService; transient private PersonService personService; @@ -125,6 +128,15 @@ public abstract class BaseReassignDialog extends BaseDialogBean { FacesContext context = FacesContext.getCurrentInstance(); + // quick exit if not enough characters entered for a search + String search = contains.trim(); + int searchMin = Application.getClientConfig(context).getPickerSearchMinimum(); + if (search.length() < searchMin) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage(context, MSG_SEARCH_MINIMUM), searchMin)); + return new SelectItem[0]; + } + SelectItem[] items; UserTransaction tx = null; @@ -133,19 +145,25 @@ public abstract class BaseReassignDialog extends BaseDialogBean { tx = Repository.getUserTransaction(context, true); tx.begin(); - + + int maxResults = Application.getClientConfig(context).getInviteUsersMaxResults(); + // Use lucene search to retrieve user details String term = QueryParser.escape(contains.trim()); StringBuilder query = new StringBuilder(128); - query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*"); - query.append(term); - query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:"); - query.append(term); - query.append("*"); - resultSet = Repository.getServiceRegistry(context).getSearchService().query( - Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString()); + Utils.generatePersonSearch(query, term); + + SearchParameters searchParams = new SearchParameters(); + searchParams.addStore(Repository.getStoreRef()); + searchParams.setLanguage(SearchService.LANGUAGE_LUCENE); + searchParams.setQuery(query.toString()); + if (maxResults > 0) + { + searchParams.setLimit(maxResults); + searchParams.setLimitBy(LimitBy.FINAL_SIZE); + } + + resultSet = Repository.getServiceRegistry(context).getSearchService().query(searchParams); List nodes = resultSet.getNodeRefs(); ArrayList itemList = new ArrayList(nodes.size()); diff --git a/source/java/org/alfresco/web/config/ClientConfigElement.java b/source/java/org/alfresco/web/config/ClientConfigElement.java index 702fcb12db..33d837e6c0 100644 --- a/source/java/org/alfresco/web/config/ClientConfigElement.java +++ b/source/java/org/alfresco/web/config/ClientConfigElement.java @@ -85,6 +85,7 @@ public class ClientConfigElement extends ConfigElementAdapter private boolean zeroByteFileUploads = true; private boolean userGroupAdmin = true; private boolean allowUserConfig = true; + private int pickerSearchMinimum = 2; /** @@ -281,6 +282,11 @@ public class ClientConfigElement extends ConfigElementAdapter combinedElement.setUserGroupAdmin(newElement.isUserGroupAdmin()); } + if (newElement.getPickerSearchMinimum() != combinedElement.getPickerSearchMinimum()) + { + combinedElement.setPickerSearchMinimum(newElement.getPickerSearchMinimum()); + } + return combinedElement; } @@ -810,4 +816,20 @@ public class ClientConfigElement extends ConfigElementAdapter { this.allowUserConfig = allowUserConfig; } + + /** + * @return Returns the minimum number of characters for a picker search. + */ + public int getPickerSearchMinimum() + { + return this.pickerSearchMinimum; + } + + /** + * @param searchMinimum The minimum number of characters for a picker search. + */ + /*package*/ void setPickerSearchMinimum(int searchMinimum) + { + this.pickerSearchMinimum = searchMinimum; + } } diff --git a/source/java/org/alfresco/web/config/ClientElementReader.java b/source/java/org/alfresco/web/config/ClientElementReader.java index 58cadbc859..6b10c27b68 100644 --- a/source/java/org/alfresco/web/config/ClientElementReader.java +++ b/source/java/org/alfresco/web/config/ClientElementReader.java @@ -70,6 +70,7 @@ public class ClientElementReader implements ConfigElementReader public static final String ELEMENT_ZEROBYTEFILEUPLOADS = "zero-byte-file-uploads"; public static final String ELEMENT_USERGROUPADMIN = "user-group-admin"; public static final String ELEMENT_ALLOWUSERCONFIG = "allow-user-config"; + public static final String ELEMENT_PICKERSEARCHMINIMUM = "picker-search-minimum"; /** @@ -307,6 +308,13 @@ public class ClientElementReader implements ConfigElementReader { configElement.setAllowUserConfig(Boolean.parseBoolean(userConfig.getTextTrim())); } + + // get the minimum number of characters for valid picker search string + Element pickerSearchMin = element.element(ELEMENT_PICKERSEARCHMINIMUM); + if (pickerSearchMin != null) + { + configElement.setPickerSearchMinimum(Integer.parseInt(pickerSearchMin.getTextTrim())); + } } return configElement; diff --git a/source/java/org/alfresco/web/ui/common/Utils.java b/source/java/org/alfresco/web/ui/common/Utils.java index 04ad5a6b5c..77b9e8f324 100644 --- a/source/java/org/alfresco/web/ui/common/Utils.java +++ b/source/java/org/alfresco/web/ui/common/Utils.java @@ -67,6 +67,7 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NoTransformerException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.util.URLEncoder; import org.alfresco.web.app.Application; import org.alfresco.web.app.servlet.DownloadContentServlet; @@ -1051,4 +1052,22 @@ public final class Utils extends StringUtils } return userAgent; } + + /** + * Generate the Lucene query for a standard Person search. The query used is standardised + * across multiple JSF components and beans. + * + * @param query Buffer for the query + * @param term Search term + */ + public static void generatePersonSearch(StringBuilder query, String term) + { + query.append("@").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:firstName:\"*"); + query.append(term); + query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:lastName:\"*"); + query.append(term); + query.append("*\" @").append(NamespaceService.CONTENT_MODEL_PREFIX).append("\\:userName:"); + query.append(term); + query.append("*"); + } }