Added a new findSites() method for use by live-search and Site Finder (sites.get.js) for ACE-1513

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@68092 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Gethin James
2014-04-26 16:20:13 +00:00
parent 28060c9cdf
commit e6e3814951
4 changed files with 241 additions and 3 deletions

View File

@@ -58,7 +58,6 @@ import org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory;
import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.search.impl.lucene.AbstractLuceneQueryParser;
import org.alfresco.repo.security.authentication.AuthenticationContext; import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
@@ -112,6 +111,7 @@ import org.json.JSONObject;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.extensions.surf.util.AbstractLifecycleBean; import org.springframework.extensions.surf.util.AbstractLifecycleBean;
import org.springframework.extensions.surf.util.ParameterCheck; import org.springframework.extensions.surf.util.ParameterCheck;
import org.springframework.util.StringUtils;
/** /**
* Site Service Implementation. Also bootstraps the site AVM and DM stores. * Site Service Implementation. Also bootstraps the site AVM and DM stores.
@@ -810,6 +810,81 @@ public class SiteServiceImpl extends AbstractLifecycleBean implements SiteServic
return siteHomeRef; return siteHomeRef;
} }
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.site.SiteService#findSites(java.lang.String, int)
*/
@Override
public List<SiteInfo> findSites(String filter, int size)
{
List<SiteInfo> result;
NodeRef siteRoot = getSiteRoot();
if (siteRoot == null)
{
result = Collections.emptyList();
}
else
{
// get the sites that match the specified names
StringBuilder query = new StringBuilder(128);
query.append("+TYPE:\"").append(SiteModel.TYPE_SITE).append('"');
final boolean filterIsPresent = filter != null && filter.length() > 0;
if (filterIsPresent)
{
query.append(" AND (");
String escNameFilter = SearchLanguageConversion.escapeLuceneQuery(filter.replace('"', ' '));
String[] tokenizedFilter = SearchLanguageConversion.tokenizeString(escNameFilter);
query.append(" cm:name:\"" + StringUtils.trimAllWhitespace(escNameFilter) + "*\"")
.append(" OR ")
.append(" cm:title: (");
for (String token: tokenizedFilter)
{
query.append("\""+token+"*\" ");
}
// for( int i = 0; i < tokenizedFilter.length; i++)
// {
// if (i!=0) //Not first element
// {
// query.append(" AND |");
// }
// query.append(tokenizedFilter[i]+"*");
// }
query.append(")");
query.append(" OR cm:description:\"" + escNameFilter + "\"");
query.append(")");
}
SearchParameters sp = new SearchParameters();
sp.addStore(siteRoot.getStoreRef());
sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
sp.setQuery(query.toString());
if (size > 0)
{
sp.setLimit(size);
sp.setLimitBy(LimitBy.FINAL_SIZE);
}
ResultSet results = this.searchService.query(sp);
try
{
result = new ArrayList<SiteInfo>(results.length());
for (NodeRef site : results.getNodeRefs())
{
result.add(createSiteInfo(site));
}
}
finally
{
results.close();
}
}
return result;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.alfresco.service.cmr.site.SiteService#findSites(java.lang.String, java.lang.String, int) * @see org.alfresco.service.cmr.site.SiteService#findSites(java.lang.String, java.lang.String, int)

View File

@@ -262,6 +262,24 @@ public class ScriptSiteService extends BaseScopableProcessorExtension
return makeSitesArray(siteInfos); return makeSitesArray(siteInfos);
} }
/**
* Find (search) the sites available in the repository. The returned list can optionally be filtered by name
* <p/>
*
* @param filter inclusion filter for returned sites. Only sites whose cm:name OR cm:title
* OR cm:description CONTAIN the filter string will be returned.
* @param size max results size crop if >0
*
* @return Site[] a list of the site filtered as appropriate
*
* @see SiteService#findSites(String, int) for a description of the limitations of this method.
* @since 5.0
*/
public Site[] findSites(String filter, int size)
{
List<SiteInfo> siteInfos = this.siteService.findSites(filter, size);
return makeSitesArray(siteInfos);
}
/** /**
* Converts the given List of SiteInfo objects to a JavaScript friendly array * Converts the given List of SiteInfo objects to a JavaScript friendly array
* of Site objects. * of Site objects.

View File

@@ -145,6 +145,23 @@ public interface SiteService
@NotAuditable @NotAuditable
List<SiteInfo> findSites(String filter, String sitePresetFilter, int size); List<SiteInfo> findSites(String filter, String sitePresetFilter, int size);
/**
* This method will find all {@link SiteInfo sites} available to the currently authenticated user based on
* the specified site filter and result set size.
* The filter parameter will match any sites whose {@link ContentModel#PROP_NAME cm:name}, {@link ContentModel#PROP_TITLE cm:title}
* or {@link ContentModel#PROP_DESCRIPTION cm:description} <i>contain</i> the specified string (ignoring case).
* <p/>
* Note that this method uses <a href="http://wiki.alfresco.com/wiki/Search">Alfresco Full Text Search</a> to retrieve results
* and depending on server Lucene, SOLR configuration may only offer eventually consistent results.
*
* @param filter Any supplied filter will be wrapped in asterisks (e.g. 'foo*') and used to match the sites' cm:name, cm:title or cm:description.
* @param size this parameter specifies a maximum result set size.
* @return Site objects for all matching sites up to the maximum result size.
*
* @since 5.0
*/
@NotAuditable
List<SiteInfo> findSites(String filter, int size);
/** /**
* List the available sites. This list can optionally be filtered by site name/title/description and/or site preset. * List the available sites. This list can optionally be filtered by site name/title/description and/or site preset.
* <p/> * <p/>

View File

@@ -69,7 +69,6 @@ import org.alfresco.service.cmr.tagging.TaggingService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.test_category.BaseSpringTestsCategory; import org.alfresco.test_category.BaseSpringTestsCategory;
import org.alfresco.test_category.OwnJVMTestsCategory;
import org.alfresco.util.BaseAlfrescoSpringTest; import org.alfresco.util.BaseAlfrescoSpringTest;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap; import org.alfresco.util.PropertyMap;
@@ -702,6 +701,135 @@ public class SiteServiceImplTest extends BaseAlfrescoSpringTest
assertEquals("Matched wrong number of sites using '?'", 2, sites.size()); assertEquals("Matched wrong number of sites using '?'", 2, sites.size());
} }
/**
* This test method ensures that searches with wildcards work as they should
*/
public void testfindSitesForLiveSearchWithWildcardTitles() throws Exception
{
// How many sites are there already in the repo?
List<SiteInfo> preexistingSites = this.siteService.findSites(null, 0);
final int preexistingSitesCount = preexistingSites.size();
// Create some test sites
//
// Note that the shortName can't contain an asterisk but the title can.
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveA", "getafix", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveB", "getafix1vitalstatistix", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveC", "Armorican Gaul France", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
//ACE-1428
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveD", "n3w s1t3 creat3ed 88", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveE", "n3w s1t3 creat3ed 99", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
//More scenarios
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveF", "super exciting product", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveG", "super exciting launch", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveH", "amazing sales 54", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveI", "wonderfulsupport32", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveJ", "great89service", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
this.siteService.createSite(TEST_SITE_PRESET, "siteLiveK", "my top draw", TEST_DESCRIPTION, SiteVisibility.PUBLIC);
// Get sites by matching title
List<SiteInfo> sites = this.siteService.findSites("getafix", 0);
assertNotNull(sites);
// As the name & description do not contain "asterix", this will become a search for sites whose titles match "asterix"
assertEquals("Matched wrong number of sites with title equal to 'getafix'", 2, sites.size());
// This means 'find all'
sites = this.siteService.findSites("*", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites using '*'", preexistingSitesCount + 11, sites.size());
sites = this.siteService.findSites("ge?afix", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites using '?'", 2, sites.size());
sites = this.siteService.findSites("Armorican", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("Gaul", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("France", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("Armorican Gaul", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("Armori", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("Fran", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
// sites = this.siteService.findSites("n3w s1t3 88", 0);
// assertNotNull(sites);
// assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
//
//
// sites = this.siteService.findSites("n3w s1t3 99", 0);
// assertNotNull(sites);
// assertEquals("Matched wrong number of sites for tokenized search", 1, sites.size());
sites = this.siteService.findSites("n3w s1t3", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 2, sites.size());
sites = this.siteService.findSites("s1t3", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for tokenized search", 2, sites.size());
sites = this.siteService.findSites("super", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for super", 2, sites.size());
sites = this.siteService.findSites("exciting", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for exciting", 2, sites.size());
sites = this.siteService.findSites("product", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for product", 1, sites.size());
// sites = this.siteService.findSites("super product", 0);
// assertNotNull(sites);
// assertEquals("Matched wrong number of sites for super product", 1, sites.size());
//
// sites = this.siteService.findSites("super launch", 0);
// assertNotNull(sites);
// assertEquals("Matched wrong number of sites for super launch", 1, sites.size());
// sites = this.siteService.findSites("exciting launch", 0);
// assertNotNull(sites);
// assertEquals("Matched wrong number of sites for super launch", 1, sites.size());
sites = this.siteService.findSites("super exciting", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for super exciting", 2, sites.size());
sites = this.siteService.findSites("amazing sales 54", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for amazing sales 54", 1, sites.size());
sites = this.siteService.findSites("wonderfulsupport32", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for wonderfulsupport32", 1, sites.size());
sites = this.siteService.findSites("great89service", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for great89service", 1, sites.size());
sites = this.siteService.findSites("top draw", 0);
assertNotNull(sites);
assertEquals("Matched wrong number of sites for top draw", 1, sites.size());
}
public void testGetSite() public void testGetSite()
{ {
// Get a site that isn't there // Get a site that isn't there