diff --git a/config/alfresco/public-rest-context.xml b/config/alfresco/public-rest-context.xml
index bfe5e94778..0dff80d818 100644
--- a/config/alfresco/public-rest-context.xml
+++ b/config/alfresco/public-rest-context.xml
@@ -551,8 +551,8 @@
+
-
diff --git a/source/java/org/alfresco/rest/api/Queries.java b/source/java/org/alfresco/rest/api/Queries.java
index 5c2a162901..c8b487872e 100644
--- a/source/java/org/alfresco/rest/api/Queries.java
+++ b/source/java/org/alfresco/rest/api/Queries.java
@@ -26,31 +26,56 @@
package org.alfresco.rest.api;
+import org.alfresco.model.ContentModel;
import org.alfresco.rest.api.model.Node;
+import org.alfresco.rest.api.model.Person;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
+import org.alfresco.rest.framework.webscripts.ResourceWebScriptHelper;
/**
* Queries API
*
* @author janv
+ * @author Alan Davis
*/
public interface Queries
{
+ // General
+ static String PARAM_TERM = "term";
+ static String PARAM_ORDERBY = ResourceWebScriptHelper.PARAM_ORDERBY;
+ static String PARAM_FIELDS = ResourceWebScriptHelper.PARAM_FILTER_FIELDS;
+ static String PARAM_INCLUDE = ResourceWebScriptHelper.PARAM_INCLUDE;
+
+ // Node query
+ static String PARAM_ROOT_NODE_ID = "rootNodeId";
+ static String PARAM_NODE_TYPE = "nodeType";
+ static String PARAM_NAME = "name";
+ static String PARAM_CREATEDAT = "createdAt";
+ static String PARAM_MODIFIEDAT = "modifiedAt";
+ static int MIN_TERM_LENGTH_NODES = 3;
+
+ // People query
+ static String PARAM_USERNAME = ContentModel.PROP_USERNAME.getLocalName();
+ static String PARAM_FIRSTNAME = ContentModel.PROP_FIRSTNAME.getLocalName();
+ static String PARAM_LASTNAME = ContentModel.PROP_LASTNAME.getLocalName();
+ static int MIN_TERM_LENGTH_PEOPLE = 2;
+
/**
* Find Nodes
*
- * @param queryId currently expects "live-search-nodes"
* @param parameters the {@link Parameters} object to get the parameters passed into the request
+ *
* @return the search query results
*/
- CollectionWithPagingInfo findNodes(String queryId, Parameters parameters);
+ CollectionWithPagingInfo findNodes(Parameters parameters);
- String PARAM_TERM = "term";
- String PARAM_ROOT_NODE_ID = "rootNodeId";
- String PARAM_NODE_TYPE = "nodeType";
-
- String PARAM_NAME = "name";
- String PARAM_CREATEDAT = "createdAt";
- String PARAM_MODIFIEDAT = "modifiedAt";
+ /**
+ * Find People
+ *
+ * @param parameters the {@link Parameters} object to get the parameters passed into the request
+ *
+ * @return the search query results
+ */
+ CollectionWithPagingInfo findPeople(Parameters parameters);
}
diff --git a/source/java/org/alfresco/rest/api/impl/QueriesImpl.java b/source/java/org/alfresco/rest/api/impl/QueriesImpl.java
index 8d245a6584..8a6d90c51b 100644
--- a/source/java/org/alfresco/rest/api/impl/QueriesImpl.java
+++ b/source/java/org/alfresco/rest/api/impl/QueriesImpl.java
@@ -26,15 +26,30 @@
package org.alfresco.rest.api.impl;
+import static org.alfresco.rest.api.impl.QueriesImpl.AbstractQuery.Sort.IN_QUERY_SORT;
+import static org.alfresco.rest.api.impl.QueriesImpl.AbstractQuery.Sort.POST_QUERY_SORT;
+
+import java.io.Serializable;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.alfresco.model.ContentModel;
import org.alfresco.query.PagingRequest;
import org.alfresco.rest.api.Nodes;
+import org.alfresco.rest.api.People;
import org.alfresco.rest.api.Queries;
import org.alfresco.rest.api.model.Node;
+import org.alfresco.rest.api.model.Person;
import org.alfresco.rest.api.model.UserInfo;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
-import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Paging;
import org.alfresco.rest.framework.resource.parameters.Parameters;
@@ -46,8 +61,8 @@ 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.repository.StoreRef;
+import org.alfresco.service.cmr.search.PermissionEvaluationMode;
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.namespace.NamespaceService;
@@ -55,68 +70,78 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
import org.alfresco.util.ParameterCheck;
import org.springframework.beans.factory.InitializingBean;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
+ * Queries implementation
+ *
* @author janv
+ * @author Alan Davis
*/
public class QueriesImpl implements Queries, InitializingBean
{
+ private final static Map NODE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
+ PARAM_NAME, ContentModel.PROP_NAME,
+ PARAM_CREATEDAT, ContentModel.PROP_CREATED,
+ PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
+
+ private final static Map PEOPLE_SORT_PARAMS_TO_QNAMES = sortParamsToQNames(
+ ContentModel.PROP_USERNAME,
+ ContentModel.PROP_FIRSTNAME,
+ ContentModel.PROP_LASTNAME);
+
+ /**
+ * 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
+ * be followed by a QName to which it maps. If however it is a QName the local name of the OName
+ * is used as the sort parameter name.
+ * @param parameters to build up the map.
+ * @return the map
+ */
+ private static Map sortParamsToQNames(Object... parameters)
+ {
+ Map map = new HashMap<>();
+ for (int i=0; i MAP_PARAM_SORT_QNAME;
- static
- {
- Map aMap = new HashMap<>(3);
-
- aMap.put(PARAM_NAME, ContentModel.PROP_NAME);
- aMap.put(PARAM_CREATEDAT, ContentModel.PROP_CREATED);
- aMap.put(PARAM_MODIFIEDAT, ContentModel.PROP_MODIFIED);
-
- MAP_PARAM_SORT_QNAME = Collections.unmodifiableMap(aMap);
- }
-
-
private Nodes nodes;
+ private People people;
public void setServiceRegistry(ServiceRegistry sr)
{
this.sr = sr;
}
- public void setTermMinLength(int termMinLength)
- {
- TERM_MIN_LEN = termMinLength;
- }
-
public void setNodes(Nodes nodes)
{
this.nodes = nodes;
}
+ public void setPeople(People people)
+ {
+ this.people = people;
+ }
+
@Override
public void afterPropertiesSet()
{
ParameterCheck.mandatory("sr", this.sr);
ParameterCheck.mandatory("nodes", this.nodes);
+ ParameterCheck.mandatory("people", this.people);
this.searchService = sr.getSearchService();
this.nodeService = sr.getNodeService();
@@ -125,100 +150,287 @@ public class QueriesImpl implements Queries, InitializingBean
}
@Override
- public CollectionWithPagingInfo findNodes(String queryId, Parameters parameters)
+ public CollectionWithPagingInfo findNodes(Parameters parameters)
{
- if (! QUERY_LIVE_SEARCH_NODES.equals(queryId))
+ return new AbstractQuery(nodeService, searchService)
{
- throw new NotFoundException(queryId);
- }
-
- StringBuilder sb = new StringBuilder();
-
- String term = parameters.getParameter(PARAM_TERM);
- if (term == null)
- {
- throw new InvalidArgumentException("Query 'term' not specified");
- }
- else
- {
- String s = term.trim();
- int cnt = 0;
- for (int i = 0; i < s.length(); i++)
+ private final Map mapUserInfo = new HashMap<>(10);
+
+ @Override
+ protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
{
- char c = s.charAt(i);
+ sp.addQueryTemplate(queryTemplateName, "%(cm:name cm:title cm:description TEXT TAG)");
+
+ String rootNodeId = parameters.getParameter(PARAM_ROOT_NODE_ID);
+ if (rootNodeId != null)
+ {
+ NodeRef nodeRef = nodes.validateOrLookupNode(rootNodeId, null);
+ query.append("PATH:\"").append(getQNamePath(nodeRef.getId())).append("//*\" AND (");
+ }
+ query.append(term);
+ if (rootNodeId != null)
+ {
+ query.append(")");
+ }
+
+ String nodeTypeStr = parameters.getParameter(PARAM_NODE_TYPE);
+ if (nodeTypeStr != null)
+ {
+ QName filterNodeTypeQName = nodes.createQName(nodeTypeStr);
+ if (dictionaryService.getType(filterNodeTypeQName) == null)
+ {
+ throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr);
+ }
+
+ query.append(" AND (+TYPE:\"").append(nodeTypeStr).append(("\")"));
+ query.append(" AND -ASPECT:\"sys:hidden\" AND -cm:creator:system AND -QNAME:comment\\-* ");
+ }
+ else
+ {
+ query.append(" AND (+TYPE:\"cm:content\" OR +TYPE:\"cm:folder\")");
+ query.append(" AND -TYPE:\"cm:thumbnail\" AND -TYPE:\"cm:failedThumbnail\" AND -TYPE:\"cm:rating\" AND -TYPE:\"fm:post\"");
+ query.append(" AND -TYPE:\"st:site\" AND -ASPECT:\"st:siteContainer\"");
+ query.append(" AND -ASPECT:\"sys:hidden\" AND -cm:creator:system AND -QNAME:comment\\-* ");
+ }
+ }
+
+ private String getQNamePath(String nodeId)
+ {
+ NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
+
+ Map cache = new HashMap<>();
+ StringBuilder buf = new StringBuilder(128);
+ Path path = null;
+ try
+ {
+ path = nodeService.getPath(nodeRef);
+ }
+ catch (InvalidNodeRefException inre)
+ {
+ throw new EntityNotFoundException(nodeId);
+ }
+
+ for (Path.Element e : path)
+ {
+ if (e instanceof Path.ChildAssocElement)
+ {
+ QName qname = ((Path.ChildAssocElement) e).getRef().getQName();
+ if (qname != null)
+ {
+ String prefix = cache.get(qname.getNamespaceURI());
+ if (prefix == null)
+ {
+ // first request for this namespace prefix, get and cache result
+ Collection prefixes = namespaceService.getPrefixes(qname.getNamespaceURI());
+ prefix = prefixes.size() != 0 ? prefixes.iterator().next() : "";
+ cache.put(qname.getNamespaceURI(), prefix);
+ }
+ buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName()));
+ }
+ }
+ else
+ {
+ buf.append('/').append(e.toString());
+ }
+ }
+ return buf.toString();
+ }
+
+ @Override
+ protected List newList(int capacity)
+ {
+ return new ArrayList(capacity);
+ }
+
+ @Override
+ protected Node convert(NodeRef nodeRef, List includeParam)
+ {
+ return nodes.getFolderOrDocument(nodeRef, null, null, includeParam, mapUserInfo);
+ }
+ }.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_NODES, "keywords",
+ IN_QUERY_SORT, NODE_SORT_PARAMS_TO_QNAMES,
+ new SortColumn(PARAM_MODIFIEDAT, false));
+ }
+
+ @Override
+ public CollectionWithPagingInfo findPeople(Parameters parameters)
+ {
+ return new AbstractQuery(nodeService, searchService)
+ {
+ @Override
+ protected void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName)
+ {
+ sp.addQueryTemplate(queryTemplateName, "|%firstName OR |%lastName OR |%userName");
+ sp.setExcludeTenantFilter(false);
+ sp.setPermissionEvaluation(PermissionEvaluationMode.EAGER);
+
+ query.append("TYPE:\"").append(ContentModel.TYPE_PERSON).append("\" AND (\"*");
+ query.append(term);
+ query.append("*\")");
+ }
+
+ @Override
+ protected List newList(int capacity)
+ {
+ return new ArrayList(capacity);
+ }
+
+ @Override
+ protected Person convert(NodeRef nodeRef, List includeParam)
+ {
+ String personId = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
+ Person person = people.getPerson(personId);
+ return person;
+ }
+
+ // TODO Do the sort in the query on day. A comment in the code for the V0 API used for live people
+ // search says adding sort values for this query don't work - tried it and they really don't.
+ }.find(parameters, PARAM_TERM, MIN_TERM_LENGTH_PEOPLE, "_PERSON",
+ POST_QUERY_SORT, PEOPLE_SORT_PARAMS_TO_QNAMES,
+ new SortColumn(PARAM_FIRSTNAME, true), new SortColumn(PARAM_LASTNAME, true));
+ }
+
+ public abstract static class AbstractQuery
+ {
+ public enum Sort
+ {
+ IN_QUERY_SORT, POST_QUERY_SORT
+ }
+
+ private final NodeService nodeService;
+ private final SearchService searchService;
+
+ public AbstractQuery(NodeService nodeService, SearchService searchService)
+ {
+ this.nodeService = nodeService;
+ this.searchService = searchService;
+ }
+
+ public CollectionWithPagingInfo find(Parameters parameters,
+ String termName, int minTermLength, String queryTemplateName, Sort sort, Map sortParamsToQNames, SortColumn... defaultSort)
+ {
+ SearchParameters sp = new SearchParameters();
+ sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
+ sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
+ sp.setDefaultFieldName(queryTemplateName);
+
+ String term = getTerm(parameters, termName, minTermLength);
+
+ StringBuilder query = new StringBuilder();
+ buildQuery(query, term, sp, queryTemplateName);
+ sp.setQuery(query.toString());
+
+ List defaultSortCols = Arrays.asList(defaultSort);
+ if (sort == IN_QUERY_SORT)
+ {
+ addSortOrder(parameters, sortParamsToQNames, defaultSortCols, sp);
+ }
+
+ Paging paging = parameters.getPaging();
+ PagingRequest pagingRequest = Util.getPagingRequest(paging);
+ sp.setSkipCount(pagingRequest.getSkipCount());
+ sp.setMaxItems(pagingRequest.getMaxItems());
+
+ ResultSet queryResults = null;
+ List colection = null;
+ try
+ {
+ queryResults = searchService.query(sp);
+
+ List nodeRefs = queryResults.getNodeRefs();
+
+ if (sort == POST_QUERY_SORT)
+ {
+ nodeRefs = postQuerySort(parameters, sortParamsToQNames, defaultSortCols, nodeRefs);
+ }
+
+ colection = newList(nodeRefs.size());
+ List includeParam = parameters.getInclude();
+
+ for (NodeRef nodeRef : nodeRefs)
+ {
+ T t = convert(nodeRef, includeParam);
+ colection.add(t);
+ }
+ }
+ finally
+ {
+ if (queryResults != null)
+ {
+ queryResults.close();
+ }
+ }
+
+ return CollectionWithPagingInfo.asPaged(paging, colection, queryResults.hasMore(), new Long(queryResults.getNumberFound()).intValue());
+ }
+
+ /**
+ * Builds up the query and is expected to call {@link SearchParameters#setDefaultFieldName(String)}
+ * and {@link SearchParameters#addQueryTemplate(String, String)}
+ * @param query StringBuilder into which the query should be built.
+ * @param term to be searched for
+ * @param sp SearchParameters
+ * @param queryTemplateName
+ */
+ protected abstract void buildQuery(StringBuilder query, String term, SearchParameters sp, String queryTemplateName);
+
+ /**
+ * Returns a list of the correct type.
+ * @param capacity of the list
+ * @return a new list.
+ */
+ protected abstract List newList(int capacity);
+
+ /**
+ * Converts a nodeRef into the an object of the required type.
+ * @param nodeRef to be converted
+ * @param includeParam additional fields to be included
+ * @return the object
+ */
+ protected abstract T convert(NodeRef nodeRef, List includeParam);
+
+ private String getTerm(Parameters parameters, String termName, int minTermLength)
+ {
+ String term = parameters.getParameter(termName);
+ if (term == null)
+ {
+ throw new InvalidArgumentException("Query '"+termName+"' not specified");
+ }
+
+ term = term.trim();
+ term = term.replace("\"", "");
+ int cnt = 0;
+ for (int i = 0; i < term.length(); i++)
+ {
+ char c = term.charAt(i);
if (Character.isLetterOrDigit(c))
{
cnt++;
- if (cnt == TERM_MIN_LEN)
+ if (cnt == minTermLength)
{
break;
}
}
}
- if (cnt < TERM_MIN_LEN)
+ if (cnt < minTermLength)
{
- throw new InvalidArgumentException("Query 'term' is too short. Must have at least "+TERM_MIN_LEN+" alphanumeric chars");
- }
- }
-
- String rootNodeId = parameters.getParameter(PARAM_ROOT_NODE_ID);
- if (rootNodeId != null)
- {
- NodeRef nodeRef = nodes.validateOrLookupNode(rootNodeId, null);
- sb.append("PATH:\"").append(getQNamePath(nodeRef.getId())).append("//*\" AND (");
- }
-
- // this will be expanded via query template (+ default field name)
- sb.append(term);
-
- if (rootNodeId != null)
- {
- sb.append(")");
- }
-
- String nodeTypeStr = parameters.getParameter(PARAM_NODE_TYPE);
- if (nodeTypeStr != null)
- {
- QName filterNodeTypeQName = nodes.createQName(nodeTypeStr);
- if (dictionaryService.getType(filterNodeTypeQName) == null)
- {
- throw new InvalidArgumentException("Unknown filter nodeType: "+nodeTypeStr);
+ throw new InvalidArgumentException("Query '"+termName+"' is too short. Must have at least "+minTermLength+" alphanumeric chars");
}
- sb.append(" AND (+TYPE:\"").append(nodeTypeStr).append(("\")"));
- sb.append(" AND -ASPECT:\"sys:hidden\" AND -cm:creator:system AND -QNAME:comment\\-* ");
- }
- else
- {
- sb.append(" AND (+TYPE:\"cm:content\" OR +TYPE:\"cm:folder\")");
- sb.append(" AND -TYPE:\"cm:thumbnail\" AND -TYPE:\"cm:failedThumbnail\" AND -TYPE:\"cm:rating\" AND -TYPE:\"fm:post\"")
- .append(" AND -TYPE:\"st:site\" AND -ASPECT:\"st:siteContainer\"")
- .append(" AND -ASPECT:\"sys:hidden\" AND -cm:creator:system AND -QNAME:comment\\-* ");
+ return term;
}
- SearchParameters sp = new SearchParameters();
-
- sp.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
- sp.setQuery(sb.toString());
- sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
-
- // query template / default field name
- sp.addQueryTemplate(QT_FIELD, "%(cm:name cm:title cm:description TEXT TAG)");
- sp.setDefaultFieldName(QT_FIELD);
-
- Paging paging = parameters.getPaging();
- PagingRequest pagingRequest = Util.getPagingRequest(paging);
-
- sp.setSkipCount(pagingRequest.getSkipCount());
- sp.setMaxItems(pagingRequest.getMaxItems());
-
- List sortCols = parameters.getSorting();
- if ((sortCols != null) && (sortCols.size() > 0))
+ /**
+ * Adds sort order to the SearchParameters.
+ */
+ protected void addSortOrder(Parameters parameters, Map sortParamsToQNames,
+ List defaultSortCols, SearchParameters sp)
{
+ List sortCols = getSorting(parameters, defaultSortCols);
for (SortColumn sortCol : sortCols)
{
- QName sortPropQName = MAP_PARAM_SORT_QNAME.get(sortCol.column);
+ QName sortPropQName = sortParamsToQNames.get(sortCol.column);
if (sortPropQName == null)
{
throw new InvalidArgumentException("Invalid sort field: "+sortCol.column);
@@ -226,72 +438,70 @@ public class QueriesImpl implements Queries, InitializingBean
sp.addSort("@" + sortPropQName, sortCol.asc);
}
}
- else
+
+ private List getSorting(Parameters parameters, List defaultSortCols)
{
- // default sort order
- sp.addSort("@" + ContentModel.PROP_MODIFIED, false);
- }
-
- ResultSet results = searchService.query(sp);
-
- List nodeList = new ArrayList<>(results.length());
-
- final Map mapUserInfo = new HashMap<>(10);
-
- List includeParam = parameters.getInclude();
-
- for (ResultSetRow row : results)
- {
- NodeRef nodeRef = row.getNodeRef();
-
- // minimal info by default (unless "include"d otherwise)
- nodeList.add(nodes.getFolderOrDocument(nodeRef, null, null, includeParam, mapUserInfo));
- }
-
- results.close();
-
- return CollectionWithPagingInfo.asPaged(paging, nodeList, results.hasMore(), new Long(results.getNumberFound()).intValue());
- }
-
- private String getQNamePath(String nodeId)
- {
- NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
-
- Map cache = new HashMap<>();
- StringBuilder buf = new StringBuilder(128);
- Path path = null;
- try
- {
- path = nodeService.getPath(nodeRef);
- }
- catch (InvalidNodeRefException inre)
- {
- throw new EntityNotFoundException(nodeId);
- }
-
- for (Path.Element e : path)
- {
- if (e instanceof Path.ChildAssocElement)
+ List sortCols = parameters.getSorting();
+ if (sortCols == null || sortCols.size() == 0)
{
- QName qname = ((Path.ChildAssocElement) e).getRef().getQName();
- if (qname != null)
+ sortCols = defaultSortCols == null ? Collections.emptyList() : defaultSortCols;
+ }
+ return sortCols;
+ }
+
+ protected List postQuerySort(Parameters parameters, Map sortParamsToQNames,
+ List defaultSortCols, List nodeRefs)
+ {
+ final List sortCols = getSorting(parameters, defaultSortCols);
+ int sortColCount = sortCols.size();
+ if (sortColCount > 0)
+ {
+ // make copy of nodeRefs because it can be unmodifiable list.
+ nodeRefs = new ArrayList(nodeRefs);
+
+ List sortPropQNames = new ArrayList<>(sortColCount);
+ for (SortColumn sortCol : sortCols)
{
- String prefix = cache.get(qname.getNamespaceURI());
- if (prefix == null)
- {
- // first request for this namespace prefix, get and cache result
- Collection prefixes = namespaceService.getPrefixes(qname.getNamespaceURI());
- prefix = prefixes.size() != 0 ? prefixes.iterator().next() : "";
- cache.put(qname.getNamespaceURI(), prefix);
- }
- buf.append('/').append(prefix).append(':').append(ISO9075.encode(qname.getLocalName()));
+ QName sortPropQName = sortParamsToQNames.get(sortCol.column);
+ sortPropQNames.add(sortPropQName);
}
+
+ final Collator col = Collator.getInstance(I18NUtil.getLocale());
+ Collections.sort(nodeRefs, new Comparator()
+ {
+ @Override
+ public int compare(NodeRef n1, NodeRef n2)
+ {
+ int result = 0;
+ for (SortColumn sortCol : sortCols)
+ {
+ QName sortPropQName = sortParamsToQNames.get(sortCol.column);
+
+ Serializable p1 = getProperty(n1, sortPropQName);
+ Serializable p2 = getProperty(n2, sortPropQName);
+
+ result = ((p1 instanceof Long) && (p2 instanceof Long)
+ ? Long.compare((Long)p1, (Long)p2)
+ : col.compare(p1.toString(), p2))
+ * (sortCol.asc ? 1 : -1);
+
+ if (result != 0)
+ {
+ break;
+ }
+ }
+ return result;
+ }
+
+ private Serializable getProperty(NodeRef nodeRef, QName sortPropQName)
+ {
+ Serializable result = nodeService.getProperty(nodeRef, sortPropQName);
+ return result == null ? "" : result;
+ }
+
+ });
}
- else
- {
- buf.append('/').append(e.toString());
- }
+ return nodeRefs;
}
- return buf.toString();
}
}
diff --git a/source/java/org/alfresco/rest/api/queries/QueriesEntityResource.java b/source/java/org/alfresco/rest/api/queries/QueriesEntityResource.java
index efa8aeab36..b318e2953a 100644
--- a/source/java/org/alfresco/rest/api/queries/QueriesEntityResource.java
+++ b/source/java/org/alfresco/rest/api/queries/QueriesEntityResource.java
@@ -26,8 +26,8 @@
package org.alfresco.rest.api.queries;
import org.alfresco.rest.api.Queries;
-import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.framework.WebApiDescription;
+import org.alfresco.rest.framework.core.exceptions.NotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
@@ -41,8 +41,13 @@ import org.springframework.beans.factory.InitializingBean;
* @author janv
*/
@EntityResource(name="queries", title = "Queries")
-public class QueriesEntityResource implements EntityResourceAction.ReadById>, InitializingBean
+public class QueriesEntityResource implements
+ EntityResourceAction.ReadById>,
+ InitializingBean
{
+ private final static String QUERY_LIVE_SEARCH_NODES = "live-search-nodes";
+ private final static String QUERY_LIVE_SEARCH_PEOPLE = "live-search-people";
+
private Queries queries;
public void setQueries(Queries queries)
@@ -59,8 +64,16 @@ public class QueriesEntityResource implements EntityResourceAction.ReadById readById(String queryId, Parameters parameters)
+ public CollectionWithPagingInfo extends Object> readById(String queryId, Parameters parameters)
{
- return queries.findNodes(queryId, parameters);
+ switch (queryId)
+ {
+ case QUERY_LIVE_SEARCH_NODES:
+ return queries.findNodes(parameters);
+ case QUERY_LIVE_SEARCH_PEOPLE:
+ return queries.findPeople(parameters);
+ default:
+ throw new NotFoundException(queryId);
+ }
}
}
diff --git a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
index 7b4cae86e6..7a4c5e2af9 100644
--- a/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/AbstractBaseApiTest.java
@@ -45,6 +45,7 @@ import org.alfresco.rest.api.tests.client.PublicApiClient;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient.BinaryPayload;
import org.alfresco.rest.api.tests.client.PublicApiHttpClient.RequestBuilder;
import org.alfresco.rest.api.tests.client.RequestContext;
+import org.alfresco.rest.api.tests.client.data.Company;
import org.alfresco.rest.api.tests.client.data.ContentInfo;
import org.alfresco.rest.api.tests.client.data.Document;
import org.alfresco.rest.api.tests.client.data.Folder;
@@ -452,10 +453,15 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
return createUser(username, "password", null);
}
+ protected String createUser(String usernameIn, String password, TestNetwork network)
+ {
+ return createUser(new PersonInfo(usernameIn, usernameIn, usernameIn, password, null, null, null, null, null, null, null), network);
+ }
+
/**
* TODO implement as remote api call
*/
- protected String createUser(final String usernameIn, final String password, final TestNetwork network)
+ protected String createUser(final PersonInfo personInfo, final TestNetwork network)
{
final String tenantDomain = (network != null ? network.getId() : TenantService.DEFAULT_DOMAIN);
@@ -468,8 +474,8 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
{
public String doWork() throws Exception
{
- String username = repoService.getPublicApiContext().createUserName(usernameIn, tenantDomain);
- PersonInfo personInfo = new PersonInfo(username, username, username, password, null, null, null, null, null, null, null);
+ String username = repoService.getPublicApiContext().createUserName(personInfo.getUsername(), tenantDomain);
+ personInfo.setUsername(username);
RepoService.TestPerson person = repoService.createUser(personInfo, username, network);
return person.getId();
diff --git a/source/test-java/org/alfresco/rest/api/tests/ApiTest.java b/source/test-java/org/alfresco/rest/api/tests/ApiTest.java
index 253740f5c3..1db5d295b3 100644
--- a/source/test-java/org/alfresco/rest/api/tests/ApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/ApiTest.java
@@ -45,7 +45,7 @@ import org.junit.runners.Suite;
NodeApiTest.class,
NodeAssociationsApiTest.class,
NodeVersionsApiTest.class,
- QueriesApiTest.class,
+ QueriesNodesApiTest.class,
RenditionsTest.class,
SharedLinkApiTest.class,
ActivitiesPostingTest.class,
diff --git a/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java b/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java
index 19a7d44a2a..8f2c62d728 100644
--- a/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java
+++ b/source/test-java/org/alfresco/rest/api/tests/PersonInfo.java
@@ -47,16 +47,12 @@ public class PersonInfo
String location, String tel, String mob, String instantmsg,
String google)
{
- super();
- if(username == null)
- {
- throw new IllegalArgumentException();
- }
+ super();
+ setUsername(username);
this.company = company;
this.networkAdmin = false;
this.firstName = firstName;
this.lastName = lastName;
- this.username = username;
this.password = password;
this.skype = skype;
this.location = location;
@@ -64,7 +60,16 @@ public class PersonInfo
this.mob = mob;
this.instantmsg = instantmsg;
this.google = google;
- }
+ }
+
+ void setUsername(String username)
+ {
+ if (username == null)
+ {
+ throw new IllegalArgumentException();
+ }
+ this.username = username;
+ }
public boolean isNetworkAdmin()
{
diff --git a/source/test-java/org/alfresco/rest/api/tests/QueriesApiTest.java b/source/test-java/org/alfresco/rest/api/tests/QueriesNodesApiTest.java
similarity index 96%
rename from source/test-java/org/alfresco/rest/api/tests/QueriesApiTest.java
rename to source/test-java/org/alfresco/rest/api/tests/QueriesNodesApiTest.java
index 9e5910b839..b9635452bb 100644
--- a/source/test-java/org/alfresco/rest/api/tests/QueriesApiTest.java
+++ b/source/test-java/org/alfresco/rest/api/tests/QueriesNodesApiTest.java
@@ -51,15 +51,15 @@ import java.util.Map;
import static org.junit.Assert.*;
/**
-* V1 REST API tests for pre-defined 'live' search Queries
+* V1 REST API tests for pre-defined 'live' search Queries on Nodes
*
*
- * - {@literal :/alfresco/api//public/alfresco/versions/1/queries}
+ * - {@literal :/alfresco/api//public/alfresco/versions/1/queries/live-search-nodes}
*
*
* @author janv
*/
-public class QueriesApiTest extends AbstractSingleNetworkSiteTest
+public class QueriesNodesApiTest extends AbstractSingleNetworkSiteTest
{
private static final String URL_QUERIES_LSN = "queries/live-search-nodes";
@@ -220,7 +220,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// Search - include optional fields - eg. aspectNames, properties, path, isLink
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("include", "aspectNames,properties,path,isLink");
+ params.put(Queries.PARAM_INCLUDE, "aspectNames,properties,path,isLink");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, allIds, null);
@@ -319,7 +319,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
term = title+String.format("%05d", 2)+title;
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, "\""+term+"\"");
- params.put("include", "properties");
+ params.put(Queries.PARAM_INCLUDE, "properties");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
assertEquals(3, nodes.size());
@@ -331,7 +331,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
term = descrip+String.format("%05d", 3)+descrip;
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, "\""+term+"\"");
- params.put("include", "properties");
+ params.put(Queries.PARAM_INCLUDE, "properties");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
assertEquals(3, nodes.size());
@@ -483,7 +483,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - modifiedAt asc
params = new HashMap<>(1);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "modifiedAt asc");
+ params.put(Queries.PARAM_ORDERBY, "modifiedAt asc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, allIds, false);
@@ -491,7 +491,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - modifiedAt desc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "modifiedAt desc");
+ params.put(Queries.PARAM_ORDERBY, "modifiedAt desc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, allIds, true);
@@ -499,7 +499,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - createdAt asc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "createdAt asc");
+ params.put(Queries.PARAM_ORDERBY, "createdAt asc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, allIds, true);
@@ -507,7 +507,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - createdAt desc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "createdAt desc");
+ params.put(Queries.PARAM_ORDERBY, "createdAt desc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, allIds, false);
@@ -515,7 +515,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - name asc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "name asc");
+ params.put(Queries.PARAM_ORDERBY, "name asc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, idsSortedByNameAsc, true);
@@ -523,7 +523,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - name desc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "name desc");
+ params.put(Queries.PARAM_ORDERBY, "name desc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, idsSortedByNameAsc, false);
@@ -531,7 +531,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - name desc, createdAt asc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "name desc, createdAt asc");
+ params.put(Queries.PARAM_ORDERBY, "name desc, createdAt asc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, idsSortedByNameDescCreatedAtAsc, false);
@@ -539,7 +539,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// sort order - name asc, createdAt asc
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "name asc, createdAt desc");
+ params.put(Queries.PARAM_ORDERBY, "name asc, createdAt desc");
response = getAll(URL_QUERIES_LSN, paging, params, 200);
nodes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), Node.class);
checkNodeIds(nodes, idsSortedByNameDescCreatedAtAsc, true);
@@ -574,7 +574,7 @@ public class QueriesApiTest extends AbstractSingleNetworkSiteTest
// -ve test - invalid sort field
params = new HashMap<>(2);
params.put(Queries.PARAM_TERM, testTerm);
- params.put("orderBy", "invalid asc");
+ params.put(Queries.PARAM_ORDERBY, "invalid asc");
getAll(URL_QUERIES_LSN, paging, params, 400);
// -ve test - unauthenticated - belts-and-braces ;-)
diff --git a/source/test-java/org/alfresco/rest/api/tests/QueriesPeopleApiTest.java b/source/test-java/org/alfresco/rest/api/tests/QueriesPeopleApiTest.java
new file mode 100644
index 0000000000..6693043a8d
--- /dev/null
+++ b/source/test-java/org/alfresco/rest/api/tests/QueriesPeopleApiTest.java
@@ -0,0 +1,405 @@
+/*
+ * #%L
+ * Alfresco Remote API
+ * %%
+ * Copyright (C) 2005 - 2016 Alfresco Software Limited
+ * %%
+ * This file is part of the Alfresco software.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ * #L%
+ */
+package org.alfresco.rest.api.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.alfresco.rest.api.Queries.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import org.alfresco.rest.AbstractSingleNetworkSiteTest;
+import org.alfresco.rest.api.Queries;
+import org.alfresco.rest.api.tests.client.HttpResponse;
+import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
+import org.alfresco.rest.api.tests.client.data.Company;
+import org.alfresco.rest.api.tests.client.data.Person;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.sun.star.lang.IllegalArgumentException;
+
+/**
+* V1 REST API tests for pre-defined 'live' search Queries on People
+ *
+ *
+ * - {@literal :/alfresco/api//public/alfresco/versions/1/queries/people}
+ *
+ *
+ * @author Alan Davis
+ */
+public class QueriesPeopleApiTest extends AbstractSingleNetworkSiteTest
+{
+ private static final String URL_QUERIES_LSN = "queries/live-search-people";
+
+ private static String TEST_TERM_PREFIX = Long.toString(System.currentTimeMillis()/1000);
+
+ // TODO Yuck: Would like to use @BeforeClass and @AfterClass. But creating and
+ // deleting users is hard from from static methods. For the moment do it
+ // in the first and last tests, but we have to get the TEST count right!
+ private static int TEST_COUNT = 6;
+ private static int testCounter = 0;
+
+ // Test usernames
+ private static final String USER1 = TEST_TERM_PREFIX+"user1";
+ private static final String USER2 = TEST_TERM_PREFIX+"user2";
+ private static final String USER3 = TEST_TERM_PREFIX+"user3";
+ private static final String USER4 = TEST_TERM_PREFIX+"user4";
+ private static final String USER5 = TEST_TERM_PREFIX+"user5";
+ private static final String USER6 = TEST_TERM_PREFIX+"user6";
+
+ // Test firstnames
+ private static final String FIRST_A = TEST_TERM_PREFIX+"FirstA";
+ private static final String FIRST_B = TEST_TERM_PREFIX+"FirstB";
+ private static final String FIRST_C = TEST_TERM_PREFIX+"FirstC";
+
+ // Test Lastnames
+ private static final String LAST_A = TEST_TERM_PREFIX+"LastA";
+ private static final String LAST_B = TEST_TERM_PREFIX+"LastB";
+ private static final String LAST_C = TEST_TERM_PREFIX+"LastC";
+
+ private static Map testUsers = new HashMap();
+
+ // inputs
+ private String term = "";
+ private String orderBy = null;
+ private String fields = null;
+ private Paging paging;
+
+ // available for extra tests after call.
+ private Map params;
+ private HttpResponse response;
+ private List people;
+
+ // expected values
+ private int expectedStatus;
+ private String[] expectedPeople;
+
+ @Before
+ @Override
+ public void setup() throws Exception
+ {
+ super.setup();
+
+ setRequestContext(user1);
+
+ if (testCounter++ == 0)
+ {
+ createTestUsers(new String[][]
+ {
+ {USER1, FIRST_A, LAST_A},
+ {USER2, FIRST_A, LAST_B},
+ {USER3, FIRST_B, LAST_A},
+ {USER4, FIRST_C, },
+ {USER5, null, LAST_A},
+ {USER6, null, LAST_C},
+ });
+ }
+
+ paging = getPaging(0, 100);
+ params = new HashMap<>();
+ term = TEST_TERM_PREFIX;
+ orderBy = null;
+ fields = null;
+
+ // Default sort order is: firstname asc, lastname asc
+ expectedPeople = expectedPeople(USER5, USER6, USER1, USER2, USER3, USER4);
+ expectedStatus = 200;
+ }
+
+ @After
+ @Override
+ public void tearDown() throws Exception
+ {
+ super.tearDown();
+
+ if (testCounter == TEST_COUNT)
+ {
+ deleteTestUsers();
+ }
+ }
+
+ // Helper method to create users. These are deleted on tearDown.
+ // The prefix is added to the username, firstname and lastname if they exist.
+ private Map createTestUsers(String[][] userProperties) throws IllegalArgumentException
+ {
+ for (String[] properties: userProperties)
+ {
+ int l = properties.length;
+ if (l > 0)
+ {
+ PersonInfo personInfo = newPersonInfo(properties);
+ String originalUsername = personInfo.getUsername();
+ String id = createUser(personInfo, networkOne);
+ Person person = new Person(
+ id,
+ null, // Not set to originalUsername, as the returned JSON does not set it
+ true, // enabled
+ personInfo.getFirstName(),
+ personInfo.getLastName(),
+ personInfo.getCompany(),
+ personInfo.getSkype(),
+ personInfo.getLocation(),
+ personInfo.getTel(),
+ personInfo.getMob(),
+ personInfo.getInstantmsg(),
+ personInfo.getGoogle(),
+ null); // description
+ testUsers.put(originalUsername, person);
+
+ // The following would automatically delete users after a test, but
+ // we need to clear other data and as we created them we should delete
+ // them.
+ // super.users.add(id);
+ }
+ }
+ return testUsers;
+ }
+
+ private void deleteTestUsers()
+ {
+ for (String id: testUsers.keySet())
+ {
+ try
+ {
+ deleteUser(id, null);
+ }
+ catch (Exception e)
+ {
+ System.err.println("Failed to delete test user "+id);
+ }
+ }
+ testUsers.clear();
+ }
+
+ // Helper method to create a PersonInfo object
+ // first 3 parameters are username, firstname, lastname unlike PersonInfo
+ // password defaults to "password"
+ private static PersonInfo newPersonInfo(String... properties) throws IllegalArgumentException
+ {
+ int l = properties.length;
+ if (l > 17)
+ {
+ throw new IllegalArgumentException("Too many properties supplied for "+properties);
+ }
+ return new PersonInfo(
+ (l <= 1 ? null : properties[ 1]), // firstName
+ (l <= 2 ? null : properties[ 2]), // lastName
+ (l <= 0 ? null : properties[ 0]), // username
+
+ (l <= 3 || properties[ 3] == null
+ ? "password" : properties[ 3]), // password
+ (l <= 4 ? null : new Company(
+ properties[ 4], // organization
+ (l <= 5 ? null : properties[ 5]), // address1
+ (l <= 6 ? null : properties[ 6]), // address2
+ (l <= 7 ? null : properties[ 7]), // address3
+ (l <= 8 ? null : properties[ 8]), // postcode
+ (l <= 9 ? null : properties[ 9]), // telephone
+ (l <= 10 ? null : properties[10]), // fax
+ (l <= 11 ? null : properties[11]))),// email
+ (l <= 12 ? null : properties[12]), // skype
+ (l <= 13 ? null : properties[13]), // location
+ (l <= 14 ? null : properties[14]), // tel
+ (l <= 15 ? null : properties[15]), // mob
+ (l <= 16 ? null : properties[16]), // instantmsg
+ (l <= 17 ? null : properties[17])); // google
+ }
+
+ private void checkApiCall(String term, String orderBy, String fields, Paging paging,
+ int expectedStatus, String[] expectedPeople) throws Exception
+ {
+ createParamIdNotNull(Queries.PARAM_TERM, term);
+ createParamIdNotNull(Queries.PARAM_ORDERBY, orderBy);
+ createParamIdNotNull(Queries.PARAM_FIELDS, fields);
+
+ response = getAll(URL_QUERIES_LSN, paging, params, expectedStatus);
+
+ if (expectedPeople != null)
+ {
+ people = Person.parsePeople(response.getJsonResponse()).getList();
+
+ StringJoiner actual = new StringJoiner("\n");
+ StringJoiner expected = new StringJoiner("\n");
+ for (int i=0; i list = new ArrayList<>();
+ for (String id: testUserIds)
+ {
+ Person person = testUsers.get(id);
+ String string = person.toString();
+ list.add(string);
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ @Test
+ public void testOnlyTestUsersAndDefaultOrder() throws Exception
+ {
+ // Checks only test users are found as a result of using TEST_TERM_PREFIX.
+ // Also checks the default sort order.
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+ @Test
+ public void testSearchFirstname() throws Exception
+ {
+ term = FIRST_A;
+ expectedPeople = expectedPeople(USER1, USER2);
+
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+ @Test
+ public void testSearchLastName() throws Exception
+ {
+ term = LAST_A;
+ expectedPeople = expectedPeople(USER5, USER1, USER3);
+
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+ @Test
+ public void testSearchUsername() throws Exception
+ {
+ term = USER1;
+ expectedPeople = expectedPeople(USER1);
+
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+ @Test
+ public void testNoTerm() throws Exception
+ {
+ term = null;
+ expectedStatus = 400;
+ expectedPeople = null;
+
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+ @Test
+ public void testTermShorterThan2() throws Exception
+ {
+ term = "X";
+ expectedStatus = 400;
+ expectedPeople = null;
+
+ checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+ }
+
+// TODO commented out tests:
+
+// Returns 500 rather than 400
+// @Test
+// public void testUnknownOrderByField() throws Exception
+// {
+// orderBy = "rubbish";
+// expectedStatus = 400;
+//
+// checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+// }
+
+// Rubbish is taken to be "asc" - is this a bug?
+// @Test
+// public void testOrderByDirection() throws Exception
+// {
+// orderBy = "firstName rubbish, lastName asc";
+// expectedStatus = 400;
+//
+// checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+// }
+
+// Server response is 500 from the first call.
+// @Test
+// public void testOrderby() throws Exception
+// {
+// // {USER_1, FIRST_A, LAST_A},
+// // {USER_2, FIRST_A, LAST_B},
+// // {USER_3, FIRST_B, LAST_A},
+// // {USER_4, FIRST_C, },
+// // {USER_5, null, LAST_A},
+// // {USER_6, null, LAST_C},
+//
+// orderBy = "firstName asc, lastName"; // same as default (asc is default order)
+//
+// checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+//
+// orderBy = "firstName desc, lastName"; // with desc and asc
+//
+// expectedPeople = new String[] {"TODO"};
+// expectedPeople = expectedPeople(USER4, USER3, USER1, USER2, USER5, USER6);
+// }
+
+// This test causes the following exception because we did not request the id field!
+// testFields(org.alfresco.rest.api.tests.QueriesPeopleApiTest) Time elapsed: 6.21 sec <<< ERROR!
+// java.lang.IllegalArgumentException: null
+// at org.alfresco.rest.api.tests.client.data.Person.(Person.java:73)
+// at org.alfresco.rest.api.tests.client.data.Person.parsePerson(Person.java:278)
+// at org.alfresco.rest.api.tests.client.data.Person.parsePeople(Person.java:503)
+// at org.alfresco.rest.api.tests.QueriesPeopleApiTest.checkApiCall(QueriesPeopleApiTest.java:246)
+// at org.alfresco.rest.api.tests.QueriesPeopleApiTest.testFields(QueriesPeopleApiTest.java:353)
+// @Test
+// public void testFields() throws Exception
+// {
+// fields = PARAM_FIRSTNAME+", "+PARAM_LASTNAME;
+// term = LAST_A;
+// expectedPeople = new String[]
+// {
+// "lastName=LastA,", // USER5
+// "firstName=FirstA, lastName=LastA,", // USER1
+// "firstName=FirstB, lastName=LastA,", // USER3
+// };
+//
+// checkApiCall(term, orderBy, fields, paging, expectedStatus, expectedPeople);
+// }
+}
diff --git a/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java b/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java
index fda484d2e3..0d136542a6 100644
--- a/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java
+++ b/source/test-java/org/alfresco/rest/api/tests/client/data/Person.java
@@ -25,26 +25,24 @@
*/
package org.alfresco.rest.api.tests.client.data;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.Serializable;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.tenant.TenantService;
-import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging;
-import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse;
-import org.alfresco.service.namespace.QName;
-import org.json.simple.JSONArray;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.Serializable;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.rest.api.tests.client.PublicApiClient.ExpectedPaging;
+import org.alfresco.rest.api.tests.client.PublicApiClient.ListResponse;
+import org.alfresco.service.namespace.QName;
+import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
-import com.sun.star.uno.RuntimeException;
-
public class Person implements Serializable, Comparable, ExpectedComparison
{
private static final long serialVersionUID = 3185698391792389751L;
@@ -107,7 +105,7 @@ public class Person implements Serializable, Comparable, ExpectedCompari
this.enabled = enabled;
}
- public String getEmail() {
+ public String getUsername() {
return username;
}
@@ -203,7 +201,7 @@ public class Person implements Serializable, Comparable, ExpectedCompari
{
return "Person [" + (id != null ? "id=" + id + ", " : "")
+ (enabled != null ? "enabled=" + enabled + ", " : "")
- + (username != null ? "email=" + username + ", " : "")
+ + (username != null ? "username=" + username + ", " : "")
+ (firstName != null ? "firstName=" + firstName + ", " : "")
+ (lastName != null ? "lastName=" + lastName + ", " : "")
+ (company != null ? "company=" + company + ", " : "")
@@ -246,7 +244,7 @@ public class Person implements Serializable, Comparable, ExpectedCompari
String instantMessageId = (String)jsonObject.get("instantMessageId");
String googleId = (String)jsonObject.get("googleId");
String skypeId = (String)jsonObject.get("skypeId");
- String email = (String)jsonObject.get("email");
+ String username = (String)jsonObject.get("username");
String telephone = (String)jsonObject.get("telephone");
String mobile = (String)jsonObject.get("mobile");
String userId = (String)jsonObject.get("id");
@@ -265,16 +263,25 @@ public class Person implements Serializable, Comparable, ExpectedCompari
String postcode = (String)companyJSON.get("postcode");
String companyTelephone = (String)companyJSON.get("telephone");
String fax = (String)companyJSON.get("fax");
- String companyEmail = (String)companyJSON.get("email");
- company = new Company(organization, address1, address2, address3, postcode, companyTelephone, fax, companyEmail);
+ String companyEmail = (String)companyJSON.get("email");
+ if (organization != null ||
+ address2 != null ||
+ address3 != null ||
+ postcode != null ||
+ companyTelephone != null ||
+ fax != null ||
+ companyEmail != null)
+ {
+ company = new Company(organization, address1, address2, address3, postcode, companyTelephone, fax, companyEmail);
+ }
}
- Person person = new Person(userId, email, enabled, firstName, lastName, company, skypeId, location, telephone, mobile, instantMessageId, googleId, description);
+ Person person = new Person(userId, username, enabled, firstName, lastName, company, skypeId, location, telephone, mobile, instantMessageId, googleId, description);
return person;
}
public Person restriced()
{
- Person p = new Person(getId(), getEmail(), getEnabled(), getFirstName(), getLastName(), null, null, null, null, null, null, null, null);
+ Person p = new Person(getId(), getUsername(), getEnabled(), getFirstName(), getLastName(), null, null, null, null, null, null, null, null);
return p;
}