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("*");
+ }
}