mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged 5.2.N (5.2.1) to HEAD (5.2)
129193 mmuller: Merged RETURN-OF-THE-API (5.2.0) to 5.2.N (5.2.1) 129042 jvonka: V1 REST API: Sites Live Search (/queries/live-search-sites) - add experimental option (for review) to choose sort type - fix post query sort to use AlfrescoCollator rather than RuleBasedCollator (latter ignores spaces) - fix post query sort to apply paging correctly (get results first) - TODO add test REPO-232, REPO-882, REPO-883 git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@129367 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -63,7 +63,11 @@ public interface Queries
|
|||||||
static int MIN_TERM_LENGTH_PEOPLE = 2;
|
static int MIN_TERM_LENGTH_PEOPLE = 2;
|
||||||
|
|
||||||
// Sites query
|
// Sites query
|
||||||
|
static String PARAM_SITE_ID = "id";
|
||||||
|
static String PARAM_SITE_TITLE = "title";
|
||||||
|
static String PARAM_SITE_DESCRIPTION = "description";
|
||||||
static int MIN_TERM_LENGTH_SITES = 2;
|
static int MIN_TERM_LENGTH_SITES = 2;
|
||||||
|
static String PARAM_SORT_TYPE = "sortType"; // TODO review
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find Nodes
|
* Find Nodes
|
||||||
|
@@ -43,6 +43,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.repo.site.SiteModel;
|
||||||
import org.alfresco.rest.api.Nodes;
|
import org.alfresco.rest.api.Nodes;
|
||||||
import org.alfresco.rest.api.People;
|
import org.alfresco.rest.api.People;
|
||||||
import org.alfresco.rest.api.Queries;
|
import org.alfresco.rest.api.Queries;
|
||||||
@@ -72,8 +73,10 @@ import org.alfresco.service.cmr.site.SiteInfo;
|
|||||||
import org.alfresco.service.cmr.site.SiteService;
|
import org.alfresco.service.cmr.site.SiteService;
|
||||||
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.util.AlfrescoCollator;
|
||||||
import org.alfresco.util.ISO9075;
|
import org.alfresco.util.ISO9075;
|
||||||
import org.alfresco.util.ParameterCheck;
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.alfresco.util.SearchLanguageConversion;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.extensions.surf.util.I18NUtil;
|
import org.springframework.extensions.surf.util.I18NUtil;
|
||||||
|
|
||||||
@@ -95,6 +98,11 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
ContentModel.PROP_FIRSTNAME,
|
ContentModel.PROP_FIRSTNAME,
|
||||||
ContentModel.PROP_LASTNAME);
|
ContentModel.PROP_LASTNAME);
|
||||||
|
|
||||||
|
private final static Map<String, QName> SITE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
|
||||||
|
PARAM_SITE_ID, ContentModel.PROP_NAME,
|
||||||
|
PARAM_SITE_TITLE, ContentModel.PROP_TITLE,
|
||||||
|
PARAM_SITE_DESCRIPTION, ContentModel.PROP_DESCRIPTION);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to build a map of sort parameter names to QNames. This method iterates through
|
* Helper method to build a map of sort parameter names to QNames. This method iterates through
|
||||||
* the parameters. If a parameter is a String it is assumed to be a sort parameter name and will
|
* the parameters. If a parameter is a String it is assumed to be a sort parameter name and will
|
||||||
@@ -307,13 +315,44 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
@Override
|
@Override
|
||||||
public CollectionWithPagingInfo<Site> findSites(Parameters parameters)
|
public CollectionWithPagingInfo<Site> findSites(Parameters parameters)
|
||||||
{
|
{
|
||||||
// TODO Alternatively do we want to implement our own find rather than rely on SiteService ?!
|
// TODO review
|
||||||
|
AbstractQuery.Sort sortType = IN_QUERY_SORT;
|
||||||
|
String sortTypeStr = parameters.getParameter(PARAM_SORT_TYPE);
|
||||||
|
if (sortTypeStr != null) {
|
||||||
|
if (sortTypeStr.equalsIgnoreCase("in-query"))
|
||||||
|
{
|
||||||
|
sortType = IN_QUERY_SORT;
|
||||||
|
}
|
||||||
|
else if (sortTypeStr.equalsIgnoreCase("post-query"))
|
||||||
|
{
|
||||||
|
sortType = POST_QUERY_SORT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Unexpected sortType: "+sortTypeStr+" (expected in-query or post-query)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new AbstractQuery<Site>(nodeService, searchService)
|
return new AbstractQuery<Site>(nodeService, searchService)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
|
||||||
{
|
{
|
||||||
// not used
|
sp.addQueryTemplate(queryTemplateName, "%(cm:name cm:title cm:description)");
|
||||||
|
sp.setExcludeTenantFilter(false);
|
||||||
|
sp.setPermissionEvaluation(PermissionEvaluationMode.EAGER);
|
||||||
|
|
||||||
|
query.append("TYPE:\"").append(SiteModel.TYPE_SITE).append("\" AND (\"*");
|
||||||
|
query.append(term);
|
||||||
|
query.append("*\")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTerm(Parameters parameters, String termName, int minTermLength)
|
||||||
|
{
|
||||||
|
String filter = super.getTerm(parameters, termName, minTermLength);
|
||||||
|
String escNameFilter = SearchLanguageConversion.escapeLuceneQuery(filter.replace('"', ' '));
|
||||||
|
return escNameFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -325,34 +364,10 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
@Override
|
@Override
|
||||||
protected Site convert(NodeRef nodeRef, List<String> includeParam)
|
protected Site convert(NodeRef nodeRef, List<String> includeParam)
|
||||||
{
|
{
|
||||||
// not used
|
return getSite(siteService.getSite(nodeRef), true);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_SITES, "_SITE", sortType, SITE_SORT_PARAMS_TO_QNAMES, new SortColumn(PARAM_SITE_TITLE, true));
|
||||||
public CollectionWithPagingInfo<Site> find(Parameters parameters, String termName, int minTermLength,
|
|
||||||
String queryTemplateName,
|
|
||||||
Sort sort, Map<String, QName> sortParamsToQNames, SortColumn... defaultSort)
|
|
||||||
{
|
|
||||||
Paging paging = parameters.getPaging();
|
|
||||||
String term = getTerm(parameters, termName, minTermLength);
|
|
||||||
|
|
||||||
// TODO optimise paging
|
|
||||||
// TODO implement sorting (see open-question)
|
|
||||||
List<SiteInfo> siteInfos = siteService.findSites(term, Integer.MAX_VALUE);
|
|
||||||
List<Site> collection = newList(siteInfos.size());
|
|
||||||
|
|
||||||
for (SiteInfo siteInfo : siteInfos)
|
|
||||||
{
|
|
||||||
// convert
|
|
||||||
Site s = getSite(siteInfo, true);
|
|
||||||
collection.add(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return listPage(collection, paging);
|
|
||||||
}
|
|
||||||
|
|
||||||
}.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_SITES, null, null, null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: see also Sites.getSite
|
// note: see also Sites.getSite
|
||||||
@@ -399,16 +414,17 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
buildQuery(query, term, sp, queryTemplateName);
|
buildQuery(query, term, sp, queryTemplateName);
|
||||||
sp.setQuery(query.toString());
|
sp.setQuery(query.toString());
|
||||||
|
|
||||||
List<SortColumn> defaultSortCols = Arrays.asList(defaultSort);
|
Paging paging = parameters.getPaging();
|
||||||
|
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
||||||
|
|
||||||
|
List<SortColumn> defaultSortCols = (defaultSort != null ? Arrays.asList(defaultSort) : Collections.emptyList());
|
||||||
if (sort == IN_QUERY_SORT)
|
if (sort == IN_QUERY_SORT)
|
||||||
{
|
{
|
||||||
addSortOrder(parameters, sortParamsToQNames, defaultSortCols, sp);
|
addSortOrder(parameters, sortParamsToQNames, defaultSortCols, sp);
|
||||||
}
|
|
||||||
|
|
||||||
Paging paging = parameters.getPaging();
|
|
||||||
PagingRequest pagingRequest = Util.getPagingRequest(paging);
|
|
||||||
sp.setSkipCount(pagingRequest.getSkipCount());
|
sp.setSkipCount(pagingRequest.getSkipCount());
|
||||||
sp.setMaxItems(pagingRequest.getMaxItems());
|
sp.setMaxItems(pagingRequest.getMaxItems());
|
||||||
|
}
|
||||||
|
|
||||||
ResultSet queryResults = null;
|
ResultSet queryResults = null;
|
||||||
List<T> collection = null;
|
List<T> collection = null;
|
||||||
@@ -440,8 +456,15 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sort == POST_QUERY_SORT)
|
||||||
|
{
|
||||||
|
return listPage(collection, paging);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return CollectionWithPagingInfo.asPaged(paging, collection, queryResults.hasMore(), new Long(queryResults.getNumberFound()).intValue());
|
return CollectionWithPagingInfo.asPaged(paging, collection, queryResults.hasMore(), new Long(queryResults.getNumberFound()).intValue());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)}
|
* Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)}
|
||||||
@@ -549,7 +572,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
sortPropQNames.add(sortPropQName);
|
sortPropQNames.add(sortPropQName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Collator col = Collator.getInstance(I18NUtil.getLocale());
|
final Collator col = AlfrescoCollator.getInstance(I18NUtil.getLocale());
|
||||||
Collections.sort(nodeRefs, new Comparator<NodeRef>()
|
Collections.sort(nodeRefs, new Comparator<NodeRef>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
@@ -566,7 +589,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
|
|
||||||
result = ((p1 instanceof Long) && (p2 instanceof Long)
|
result = ((p1 instanceof Long) && (p2 instanceof Long)
|
||||||
? Long.compare((Long)p1, (Long)p2)
|
? Long.compare((Long)p1, (Long)p2)
|
||||||
: col.compare(p1.toString(), p2))
|
: col.compare(p1.toString(), p2.toString()))
|
||||||
* (sortCol.asc ? 1 : -1);
|
* (sortCol.asc ? 1 : -1);
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
@@ -590,7 +613,7 @@ public class QueriesImpl implements Queries, InitializingBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
// note: see also AbstractNodeRelation
|
// note: see also AbstractNodeRelation
|
||||||
protected CollectionWithPagingInfo listPage(List result, Paging paging)
|
protected static CollectionWithPagingInfo listPage(List result, Paging paging)
|
||||||
{
|
{
|
||||||
// return 'page' of results (based on full result set)
|
// return 'page' of results (based on full result set)
|
||||||
int skipCount = paging.getSkipCount();
|
int skipCount = paging.getSkipCount();
|
||||||
|
@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.site.SiteVisibility;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -210,6 +211,135 @@ public class QueriesSitesApiTest extends AbstractSingleNetworkSiteTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLiveSearchSites_Sort() throws Exception
|
||||||
|
{
|
||||||
|
setRequestContext(user1);
|
||||||
|
|
||||||
|
List<String> siteIds = new ArrayList<>(5);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// As user 1 ...
|
||||||
|
|
||||||
|
Paging paging = getPaging(0, 100);
|
||||||
|
|
||||||
|
// create site
|
||||||
|
String s1 = createSite("siABCDEF", "ABCDEF DEF", "sdABCDEF", SiteVisibility.PRIVATE, 201).getId();
|
||||||
|
String s2 = createSite("siABCD", "ABCD DEF", "sdABCD", SiteVisibility.PRIVATE, 201).getId();
|
||||||
|
String s3 = createSite("siABCDE", "ABCDE DEF", "sdABCDE", SiteVisibility.PRIVATE, 201).getId();
|
||||||
|
String s4 = createSite("siAB", "AB DEF", "sdAB", SiteVisibility.PRIVATE, 201).getId();
|
||||||
|
String s5 = createSite("siABC", "ABC DEF", "sdABC", SiteVisibility.PRIVATE, 201).getId();
|
||||||
|
|
||||||
|
siteIds.addAll(Arrays.asList(new String[] {s1, s2, s3, s4, s5}));
|
||||||
|
|
||||||
|
int sCount = siteIds.size();
|
||||||
|
|
||||||
|
// test sort order
|
||||||
|
|
||||||
|
// TODO agree and test default sort order
|
||||||
|
|
||||||
|
// sort order - id asc
|
||||||
|
Map<String, String> params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "id asc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
HttpResponse response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
List<Site> sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s4, s5, s2, s3, s1}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - id desc
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "id desc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s1, s3, s2, s5, s4}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - title asc
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "title asc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s2, s3, s5, s1, s4}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - title desc
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "title desc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s4, s1, s5, s3, s2}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - title asc (post query - using Alfresco Collator which does not ignore spaces, unlike default RuleBasedCollator)
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "title asc");
|
||||||
|
params.put("sortType", "post-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s4, s5, s2, s3, s1}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - title desc (post query - using Alfresco Collator which does not ignore spaces, unlike default RuleBasedCollator)
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "title desc");
|
||||||
|
params.put("sortType", "post-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s1, s3, s2, s5, s4}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - description asc
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "description asc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s4, s5, s2, s3, s1}), getSiteIds(sites));
|
||||||
|
|
||||||
|
// sort order - description desc
|
||||||
|
params = new HashMap<>(1);
|
||||||
|
params.put(Queries.PARAM_TERM, "siAB");
|
||||||
|
params.put(Queries.PARAM_ORDERBY, "description desc");
|
||||||
|
params.put("sortType", "in-query");
|
||||||
|
response = getAll(URL_QUERIES_LSS, paging, params, 200);
|
||||||
|
sites = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Site.class);
|
||||||
|
assertEquals(sCount, sites.size());
|
||||||
|
assertEquals(Arrays.asList(new String[] {s1, s3, s2, s5, s4}), getSiteIds(sites));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// some cleanup
|
||||||
|
setRequestContext(user1);
|
||||||
|
for (String siteId : siteIds)
|
||||||
|
{
|
||||||
|
deleteSite(siteId, true, 204);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getSiteIds(List<Site> sites)
|
||||||
|
{
|
||||||
|
List<String> siteIds = new ArrayList<>(sites.size());
|
||||||
|
for (Site site : sites)
|
||||||
|
{
|
||||||
|
siteIds.add(site.getId());
|
||||||
|
}
|
||||||
|
return siteIds;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getScope()
|
public String getScope()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user