diff --git a/config/alfresco/extension/web-client-config-custom.xml.sample b/config/alfresco/extension/web-client-config-custom.xml.sample index 78dae712a2..c212eddfdb 100644 --- a/config/alfresco/extension/web-client-config-custom.xml.sample +++ b/config/alfresco/extension/web-client-config-custom.xml.sample @@ -5,6 +5,7 @@ someone@your-domain.com + 100 --> diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 26160b9809..a542ea4083 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -764,8 +764,8 @@ home_space_name=Home Space Name title_admin_console=Administration Console admin_console=Administration Console admin_description=Use this view to perform system administration functions. -admin_limited_license=Licensed: {0} license issued on {1,date,short} limited to {2} days expiring {3,date,short} ({4} days remaining). -admin_unlimited_license=Licensed: {0} license issued on {1,date,short} (does not expire). +admin_limited_license=Licensed: {0} license granted to {1} and limited to {3} days expiring {4,date,short} ({5} days remaining - issued on {2,date,short}). +admin_unlimited_license=Licensed: {0} license granted to {1} and does not expire (issued on {2,date,short}). admin_invalid_license=Licensed: LICENSE INVALID - Alfresco Repository restricted to read-only capability. # UI Page Titles diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 9ecdb0b79a..f9fef1e0c0 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -39,6 +39,13 @@ 3 + + false + + + -1 + + @@ -138,6 +145,7 @@ + diff --git a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java index 4d7d5aabbd..106b9a7b20 100644 --- a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java +++ b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java @@ -686,8 +686,12 @@ public class AdvancedSearchBean // then simply navigating to the browse screen will cause it pickup the Search Context SearchContext search = new SearchContext(); + // set the full-text/name field value search.setText(this.text); + // set whether to force AND operation on text terms + search.setForceAndTerms(Application.getClientConfig(FacesContext.getCurrentInstance()).getForceAndTerms()); + if (this.mode.equals(MODE_ALL)) { search.setMode(SearchContext.SEARCH_ALL); diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index b116b09018..3547317fcc 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -43,8 +43,10 @@ import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; +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.namespace.QName; @@ -679,9 +681,20 @@ public class BrowseBean implements IContextListener tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true); tx.begin(); - results = this.searchService.query( - Repository.getStoreRef(), - SearchService.LANGUAGE_LUCENE, query, null, null); + // Limit search to the first 100 matches + SearchParameters sp = new SearchParameters(); + sp.setLanguage(SearchService.LANGUAGE_LUCENE); + sp.setQuery(query); + sp.addStore(Repository.getStoreRef()); + + int searchLimit = Application.getClientConfig(FacesContext.getCurrentInstance()).getSearchMaxResults(); + if(searchLimit > 0) + { + sp.setLimitBy(LimitBy.FINAL_SIZE); + sp.setLimit(searchLimit); + } + + results = this.searchService.query(sp); if (logger.isDebugEnabled()) logger.debug("Search results returned: " + results.length()); diff --git a/source/java/org/alfresco/web/bean/SearchContext.java b/source/java/org/alfresco/web/bean/SearchContext.java index 90802c92aa..5aea16661e 100644 --- a/source/java/org/alfresco/web/bean/SearchContext.java +++ b/source/java/org/alfresco/web/bean/SearchContext.java @@ -119,6 +119,9 @@ public final class SearchContext implements Serializable /** any additional fixed value attributes to add to the search, such as boolean or noderef */ private Map queryFixedValues = new HashMap(5, 1.0f); + /** set true to force the use of AND between text terms */ + private boolean forceAndTerms = false; + /** logger */ private static Log logger = LogFactory.getLog(SearchContext.class); @@ -217,6 +220,9 @@ public final class SearchContext implements Serializable term = term.substring(1); } + // special case for AND all terms if set (apply after operator character removed) + operatorAND = operatorAND | this.forceAndTerms; + if (term.length() != 0) { // operators such as AND and OR are only make sense for full text searching @@ -654,6 +660,22 @@ public final class SearchContext implements Serializable return this.queryFixedValues.get(qname); } + /** + * @return Returns if AND is forced between text terms. False (OR terms) is the default. + */ + public boolean getForceAndTerms() + { + return this.forceAndTerms; + } + + /** + * @param forceAndTerms Set true to force AND between text terms. Otherwise OR is the default. + */ + public void setForceAndTerms(boolean forceAndTerms) + { + this.forceAndTerms = forceAndTerms; + } + /** * @return this SearchContext as XML * diff --git a/source/java/org/alfresco/web/config/ClientConfigElement.java b/source/java/org/alfresco/web/config/ClientConfigElement.java index ef2ecfd302..602159cb92 100644 --- a/source/java/org/alfresco/web/config/ClientConfigElement.java +++ b/source/java/org/alfresco/web/config/ClientConfigElement.java @@ -34,6 +34,8 @@ public class ClientConfigElement extends ConfigElementAdapter private int recentSpacesItems = 6; private boolean shelfVisible = true; private int searchMinimum = 3; + private boolean forceAndTerms = false; + private int searchMaxResults = -1; private String helpUrl = null; private String editLinkType = "http"; private String homeSpacePermission = null; @@ -121,6 +123,16 @@ public class ClientConfigElement extends ConfigElementAdapter newElement.setSearchMinimum(existingElement.getSearchMinimum()); } + if (existingElement.getForceAndTerms() != newElement.getForceAndTerms()) + { + newElement.setForceAndTerms(existingElement.getForceAndTerms()); + } + + if (existingElement.getSearchMaxResults() != newElement.getSearchMaxResults()) + { + newElement.setSearchMaxResults(existingElement.getSearchMaxResults()); + } + if (existingElement.isShelfVisible() != newElement.isShelfVisible()) { newElement.setShelfVisible(existingElement.isShelfVisible()); @@ -263,6 +275,44 @@ public class ClientConfigElement extends ConfigElementAdapter { this.searchMinimum = searchMinimum; } + + /** + * @return If true enables AND text terms for simple/advanced search by default. + */ + public boolean getForceAndTerms() + { + return this.forceAndTerms; + } + + /** + * @param forceAndTerms True to enable AND text terms for simple/advanced search by default. + */ + /*package*/ void setForceAndTerms(boolean forceAndTerms) + { + this.forceAndTerms = forceAndTerms; + } + + /** + * If positive, this will limit the size of the result set from the search. + * + * @return + */ + + public int getSearchMaxResults() + { + return searchMaxResults; + } + + /** + * Set if the the result set from a search will be of limited size. + * If negative it is unlimited, by convention, this is set to -1. + * + * @param searchMaxResults + */ + /*package*/ void setSearchMaxResults(int searchMaxResults) + { + this.searchMaxResults = searchMaxResults; + } /** * @return Returns the default Home Space permissions. diff --git a/source/java/org/alfresco/web/config/ClientElementReader.java b/source/java/org/alfresco/web/config/ClientElementReader.java index 228af242e4..73cf1ecc5c 100644 --- a/source/java/org/alfresco/web/config/ClientElementReader.java +++ b/source/java/org/alfresco/web/config/ClientElementReader.java @@ -34,6 +34,8 @@ public class ClientElementReader implements ConfigElementReader public static final String ELEMENT_HELPURL = "help-url"; public static final String ELEMENT_EDITLINKTYPE = "edit-link-type"; public static final String ELEMENT_SEARCHMINIMUM = "search-minimum"; + public static final String ELEMENT_SEARCHANDTERMS = "search-and-terms"; + public static final String ELEMENT_SEARCHMAXRESULTS = "search-max-results"; public static final String ELEMENT_HOMESPACEPERMISSION = "home-space-permission"; public static final String ELEMENT_FROMEMAILADDRESS = "from-email-address"; public static final String ELEMENT_SHELFVISIBLE = "shelf-visible"; @@ -93,6 +95,20 @@ public class ClientElementReader implements ConfigElementReader configElement.setSearchMinimum(Integer.parseInt(searchMin.getTextTrim())); } + // get the search force AND terms setting + Element searchForceAnd = element.element(ELEMENT_SEARCHANDTERMS); + if (searchForceAnd != null) + { + configElement.setForceAndTerms(Boolean.parseBoolean(searchForceAnd.getTextTrim())); + } + + // get the search max results size + Element searchMaxResults = element.element(ELEMENT_SEARCHMAXRESULTS); + if (searchMaxResults != null) + { + configElement.setSearchMaxResults(Integer.parseInt(searchMaxResults.getTextTrim())); + } + // get the default permission for newly created users Home Spaces Element permission = element.element(ELEMENT_HOMESPACEPERMISSION); if (permission != null) diff --git a/source/java/org/alfresco/web/ui/repo/component/UISimpleSearch.java b/source/java/org/alfresco/web/ui/repo/component/UISimpleSearch.java index 16e954c113..ecc375ff66 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UISimpleSearch.java +++ b/source/java/org/alfresco/web/ui/repo/component/UISimpleSearch.java @@ -132,6 +132,7 @@ public class UISimpleSearch extends UICommand */ public void broadcast(FacesEvent event) throws AbortProcessingException { + FacesContext fc = getFacesContext(); if (event instanceof SearchEvent) { // update the component parameters from the search event details @@ -141,6 +142,7 @@ public class UISimpleSearch extends UICommand SearchContext context = new SearchContext(); context.setText(searchEvent.SearchText); context.setMode(searchEvent.SearchMode); + context.setForceAndTerms(Application.getClientConfig(fc).getForceAndTerms()); this.search = context; super.broadcast(event); @@ -149,7 +151,6 @@ public class UISimpleSearch extends UICommand { // special case to navigate to the advanced search screen AdvancedSearchEvent searchEvent = (AdvancedSearchEvent)event; - FacesContext fc = getFacesContext(); fc.getApplication().getNavigationHandler().handleNavigation(fc, null, searchEvent.Outcome); // NOTE: we don't call super() here so that our nav outcome is the one that occurs!