mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merged V4.1-BUG-FIX to HEAD
42725: Record Only Merge: V3.4-BUG-FIX (3.4.12) to V4.1-BUG-FIX (4.1.2) << Record only as 4.1.2 used PDFBOX 1.0.7 rather than 1.0.6 >> 42721: ALF-14185 PDF not indexed as a result of PDFBOX-1143 workaround in Tika 42726: ALF-16388 CLONE: PDF not indexed as a result of PDFBOX-1143 workaround in Tika - 4.1 specific fix (uses PDFBox 1.0.7) for the same issue as ALF-14185 on 3.4 (uses PDFBox 1.0.6). 42736: ALF-16093: Implement new getPeople CQ (eg. if using user admin console and/or Solr unavailable) 42740: Merged DEV to V4.1-BUG-FIX 42626: ALF-14336: SOLR indexing fails with unterminated string for PDF uploaded Appeared exception due to postgreSQL (http://archives.postgresql.org/pgsql-jdbc/2007-02/msg00107.php). Remove '\u0000' characters from the property. 42741: Fix for ALF-16332 - Alternative version of AbstractWebScriptViewResolver that uses a ConcurrentHashMap and thus allows multiple views to be resolved at the same time! 42755: Merged DEV to V4.1-BUG-FIX 42750 : ALF-16315 42762: ALF-15616: Merged V3.4-BUG-FIX (3.4.12) to V4.1-BUG-FIX (4.1.2) 42758: ALF-11956 WCM accessibility - tabIndex code. See comment on 17 Oct 2012 "4) TinyMCE fields are not accessible using the keyboard (you have to use the mouse to select the "click to edit" option) - > It's reproduced for (+) icon, content created on press-release.xsd." 42768: Merged somehow-lost mergeinfo from r42679 42769: Merged V3.4-BUG-FIX to V4.1-BUG-FIX 42738: ALF-12724 CLONE - Activities trigger high CPU usage and lock contention 42767: Merged V3.4 to V3.4-BUG-FIX 42727: ALF-16366: PermissionService calls were updating nodes but not reindexing them, leaving out of sync transactions after a clean bootstrap! git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@42770 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -339,6 +339,7 @@
|
|||||||
<property name="storageType" value="org.alfresco.query.CannedQueryFactory"/>
|
<property name="storageType" value="org.alfresco.query.CannedQueryFactory"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<!-- deprecated (see getPeopleCannedQueryFactory) -->
|
||||||
<bean name="peopleGetChildrenCannedQueryFactory" class="org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory">
|
<bean name="peopleGetChildrenCannedQueryFactory" class="org.alfresco.repo.node.getchildren.GetChildrenCannedQueryFactory">
|
||||||
<property name="registry" ref="personServiceCannedQueryRegistry"/>
|
<property name="registry" ref="personServiceCannedQueryRegistry"/>
|
||||||
<property name="dictionaryService" ref="dictionaryService"/>
|
<property name="dictionaryService" ref="dictionaryService"/>
|
||||||
@@ -351,6 +352,14 @@
|
|||||||
<property name="methodSecurity" ref="PersonService_security_getPeople"/>
|
<property name="methodSecurity" ref="PersonService_security_getPeople"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean name="getPeopleCannedQueryFactory" class="org.alfresco.repo.security.person.GetPeopleCannedQueryFactory">
|
||||||
|
<property name="registry" ref="personServiceCannedQueryRegistry"/>
|
||||||
|
<property name="tenantService" ref="tenantService"/>
|
||||||
|
<property name="nodeDAO" ref="nodeDAO"/>
|
||||||
|
<property name="qnameDAO" ref="qnameDAO"/>
|
||||||
|
<property name="cannedQueryDAO" ref="cannedQueryDAO"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean name="personServicePermissionsManager" class="org.alfresco.repo.security.person.PermissionsManagerImpl" >
|
<bean name="personServicePermissionsManager" class="org.alfresco.repo.security.person.PermissionsManagerImpl" >
|
||||||
<property name="permissionService">
|
<property name="permissionService">
|
||||||
<ref bean="permissionServiceImpl" />
|
<ref bean="permissionServiceImpl" />
|
||||||
|
@@ -72,13 +72,16 @@ Inbound settings from iBatis
|
|||||||
<typeAlias alias="ChildProperty" type="org.alfresco.repo.domain.node.ChildPropertyEntity"/>
|
<typeAlias alias="ChildProperty" type="org.alfresco.repo.domain.node.ChildPropertyEntity"/>
|
||||||
<typeAlias alias="PrimaryChildrenAclUpdate" type="org.alfresco.repo.domain.node.PrimaryChildrenAclUpdateEntity"/>
|
<typeAlias alias="PrimaryChildrenAclUpdate" type="org.alfresco.repo.domain.node.PrimaryChildrenAclUpdateEntity"/>
|
||||||
|
|
||||||
<!--GetChildren CQ (currently used by FileFolderService.list / PersonService.getPeople) -->
|
<!--GetChildren CQ (currently used by FileFolderService.list) -->
|
||||||
<typeAlias alias="FilterSortNode" type="org.alfresco.repo.node.getchildren.FilterSortNodeEntity"/>
|
<typeAlias alias="FilterSortNode" type="org.alfresco.repo.node.getchildren.FilterSortNodeEntity"/>
|
||||||
|
|
||||||
<!--GetChildren by Auditable CQ -->
|
<!--GetChildren by Auditable CQ -->
|
||||||
<typeAlias alias="NodeBackedEntity" type="org.alfresco.repo.query.NodeBackedEntity"/>
|
<typeAlias alias="NodeBackedEntity" type="org.alfresco.repo.query.NodeBackedEntity"/>
|
||||||
<typeAlias alias="NodeWithTargetsEntity" type="org.alfresco.repo.query.NodeWithTargetsEntity"/>
|
<typeAlias alias="NodeWithTargetsEntity" type="org.alfresco.repo.query.NodeWithTargetsEntity"/>
|
||||||
|
|
||||||
|
<!--GetPeople CQ (currently used by PersonService.getPeople) -->
|
||||||
|
<typeAlias alias="FilterSortPerson" type="org.alfresco.repo.security.person.FilterSortPersonEntity"/>
|
||||||
|
|
||||||
<!-- Authority CQ -->
|
<!-- Authority CQ -->
|
||||||
<typeAlias alias="AuthorityInfo" type="org.alfresco.repo.security.authority.AuthorityInfoEntity"/>
|
<typeAlias alias="AuthorityInfo" type="org.alfresco.repo.security.authority.AuthorityInfoEntity"/>
|
||||||
|
|
||||||
@@ -223,6 +226,7 @@ Inbound settings from iBatis
|
|||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-auditable-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-auditable-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-authorities-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-authorities-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-blogs-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-blogs-common-SqlMap.xml"/>
|
||||||
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-people-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-calendar-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-calendar-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-copy-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-copy-common-SqlMap.xml"/>
|
||||||
<mapper resource="alfresco/ibatis/#resource.dialect#/query-downloads-common-SqlMap.xml"/>
|
<mapper resource="alfresco/ibatis/#resource.dialect#/query-downloads-common-SqlMap.xml"/>
|
||||||
|
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="alfresco.query.people">
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
<!-- Result Maps -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<!-- GetPeople Canned Query -->
|
||||||
|
|
||||||
|
<select id="select_GetPeopleCannedQuery" parameterType="FilterSortPerson" resultType="String">
|
||||||
|
select
|
||||||
|
childNode.uuid as uuid
|
||||||
|
from
|
||||||
|
alf_child_assoc assoc
|
||||||
|
join alf_node childNode on (childNode.id = assoc.child_node_id)
|
||||||
|
<if test="prop1qnameId != null">
|
||||||
|
left join alf_node_properties prop1 on (prop1.node_id = childNode.id and prop1.qname_id = #{prop1qnameId})
|
||||||
|
</if>
|
||||||
|
<if test="prop2qnameId != null">
|
||||||
|
left join alf_node_properties prop2 on (prop2.node_id = childNode.id and prop2.qname_id = #{prop2qnameId})
|
||||||
|
</if>
|
||||||
|
<if test="prop3qnameId != null">
|
||||||
|
left join alf_node_properties prop3 on (prop3.node_id = childNode.id and prop3.qname_id = #{prop3qnameId})
|
||||||
|
</if>
|
||||||
|
where
|
||||||
|
assoc.parent_node_id = #{parentNodeId}
|
||||||
|
<if test="prop1qnameId != null">
|
||||||
|
and
|
||||||
|
(
|
||||||
|
prop1.string_value like #{pattern} <include refid="alfresco.util.escape"/>
|
||||||
|
</if>
|
||||||
|
<if test="prop2qnameId != null">
|
||||||
|
or prop2.string_value like #{pattern} <include refid="alfresco.util.escape"/>
|
||||||
|
</if>
|
||||||
|
<if test="prop3qnameId != null">
|
||||||
|
or prop3.string_value like #{pattern} <include refid="alfresco.util.escape"/>
|
||||||
|
</if>
|
||||||
|
<if test="prop1qnameId != null">
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
<if test="sort1asc != null">
|
||||||
|
order by
|
||||||
|
prop1.string_value <if test="sort1asc == true">ASC</if><if test="sort1asc == false">DESC</if>
|
||||||
|
</if>
|
||||||
|
<if test="sort2asc != null">
|
||||||
|
, prop2.string_value <if test="sort2asc == true">ASC</if><if test="sort2asc == false">DESC</if>
|
||||||
|
</if>
|
||||||
|
<if test="sort3asc != null">
|
||||||
|
, prop3.string_value <if test="sort3asc == true">ASC</if><if test="sort3asc == false">DESC</if>
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -64,8 +64,6 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
|
|
||||||
private RepoCtx ctx = null;
|
private RepoCtx ctx = null;
|
||||||
|
|
||||||
private volatile boolean busy;
|
|
||||||
|
|
||||||
public void setActivityPostServiceImpl(ActivityPostServiceImpl activityPostServiceImpl)
|
public void setActivityPostServiceImpl(ActivityPostServiceImpl activityPostServiceImpl)
|
||||||
{
|
{
|
||||||
this.activityPostServiceImpl = activityPostServiceImpl;
|
this.activityPostServiceImpl = activityPostServiceImpl;
|
||||||
@@ -135,8 +133,6 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
{
|
{
|
||||||
ctx = new RepoCtx(sysAdminParams, repoEndPoint);
|
ctx = new RepoCtx(sysAdminParams, repoEndPoint);
|
||||||
ctx.setUserNamesAreCaseSensitive(userNamesAreCaseSensitive);
|
ctx.setUserNamesAreCaseSensitive(userNamesAreCaseSensitive);
|
||||||
|
|
||||||
busy = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,11 +147,6 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
|
|
||||||
abstract public int getEstimatedGridSize();
|
abstract public int getEstimatedGridSize();
|
||||||
|
|
||||||
protected boolean isActive()
|
|
||||||
{
|
|
||||||
return busy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute() throws JobExecutionException
|
public void execute() throws JobExecutionException
|
||||||
{
|
{
|
||||||
checkProperties();
|
checkProperties();
|
||||||
@@ -171,10 +162,11 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
String lockToken = null;
|
String lockToken = null;
|
||||||
|
LockCallback lockCallback = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
JobLockRefreshCallback lockCallback = new LockCallback();
|
lockCallback = new LockCallback();
|
||||||
lockToken = acquireLock(lockCallback);
|
lockToken = acquireLock(lockCallback);
|
||||||
|
|
||||||
|
|
||||||
@@ -213,7 +205,7 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
releaseLock(lockToken);
|
releaseLock(lockCallback, lockToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +213,8 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
|
|
||||||
private class LockCallback implements JobLockRefreshCallback
|
private class LockCallback implements JobLockRefreshCallback
|
||||||
{
|
{
|
||||||
|
private volatile boolean busy = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive()
|
public boolean isActive()
|
||||||
{
|
{
|
||||||
@@ -251,7 +245,7 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
// Got the lock - now register the refresh callback which will keep the lock alive
|
// Got the lock - now register the refresh callback which will keep the lock alive
|
||||||
jobLockService.refreshLock(lockToken, LOCK_QNAME, LOCK_TTL, lockCallback);
|
jobLockService.refreshLock(lockToken, LOCK_QNAME, LOCK_TTL, lockCallback);
|
||||||
|
|
||||||
busy = true;
|
((LockCallback)lockCallback).busy = true;
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
@@ -261,11 +255,11 @@ public abstract class AbstractFeedGenerator implements FeedGenerator
|
|||||||
return lockToken;
|
return lockToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseLock(String lockToken)
|
private void releaseLock(LockCallback lockCallback, String lockToken)
|
||||||
{
|
{
|
||||||
if (lockToken != null)
|
if (lockCallback != null && lockToken != null)
|
||||||
{
|
{
|
||||||
busy = false;
|
((LockCallback)lockCallback).busy = false;
|
||||||
|
|
||||||
jobLockService.releaseLock(lockToken, LOCK_QNAME);
|
jobLockService.releaseLock(lockToken, LOCK_QNAME);
|
||||||
|
|
||||||
|
@@ -969,6 +969,10 @@ abstract public class AbstractMappingMetadataExtracter implements MetadataExtrac
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(valueStr.indexOf("\u0000") != -1)
|
||||||
|
{
|
||||||
|
valueStr = valueStr.replaceAll("\u0000", "");
|
||||||
|
}
|
||||||
// Keep the trimmed value
|
// Keep the trimmed value
|
||||||
value = valueStr;
|
value = valueStr;
|
||||||
}
|
}
|
||||||
|
@@ -1831,6 +1831,13 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// The node's version has moved on so no need to invalidate caches
|
// The node's version has moved on so no need to invalidate caches
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ALF-16366: Ensure index impact is accounted for. If the node is being deleted we would expect the
|
||||||
|
// appropriate events to be fired manually
|
||||||
|
if (!nodeUpdate.isUpdateTypeQNameId() || !getNodeNotNull(nodeId, false).getDeleted(qnameDAO))
|
||||||
|
{
|
||||||
|
nodeIndexer.indexUpdateNode(oldNode.getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
if (isDebugEnabled)
|
if (isDebugEnabled)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -48,7 +48,6 @@ import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
|||||||
import org.alfresco.service.cmr.security.PersonService;
|
import org.alfresco.service.cmr.security.PersonService;
|
||||||
import org.alfresco.service.cmr.security.PersonService.PersonInfo;
|
import org.alfresco.service.cmr.security.PersonService.PersonInfo;
|
||||||
import org.alfresco.service.cmr.usage.ContentUsageService;
|
import org.alfresco.service.cmr.usage.ContentUsageService;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.PropertyMap;
|
import org.alfresco.util.PropertyMap;
|
||||||
@@ -76,7 +75,6 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
private AuthorityDAO authorityDAO;
|
private AuthorityDAO authorityDAO;
|
||||||
private AuthorityService authorityService;
|
private AuthorityService authorityService;
|
||||||
private PersonService personService;
|
private PersonService personService;
|
||||||
private NamespaceService namespaceService;
|
|
||||||
private MutableAuthenticationService authenticationService;
|
private MutableAuthenticationService authenticationService;
|
||||||
private ContentUsageService contentUsageService;
|
private ContentUsageService contentUsageService;
|
||||||
private TenantService tenantService;
|
private TenantService tenantService;
|
||||||
@@ -86,6 +84,9 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
private ValueDerivingMapFactory<ScriptNode, String, Boolean> valueDerivingMapFactory;
|
private ValueDerivingMapFactory<ScriptNode, String, Boolean> valueDerivingMapFactory;
|
||||||
private int numRetries = 10;
|
private int numRetries = 10;
|
||||||
|
|
||||||
|
private int defaultListMaxResults = 5000;
|
||||||
|
|
||||||
|
private static final String HINT_CQ_SUFFIX = " [hint:useCQ]";
|
||||||
|
|
||||||
public void afterPropertiesSet() throws Exception
|
public void afterPropertiesSet() throws Exception
|
||||||
{
|
{
|
||||||
@@ -192,11 +193,6 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
this.personService = personService;
|
this.personService = personService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNamespaceService(NamespaceService namespaceService)
|
|
||||||
{
|
|
||||||
this.namespaceService = namespaceService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentUsageService the ContentUsageService to set
|
* @param contentUsageService the ContentUsageService to set
|
||||||
*/
|
*/
|
||||||
@@ -233,6 +229,11 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
this.userRegistrySynchronizer = userRegistrySynchronizer;
|
this.userRegistrySynchronizer = userRegistrySynchronizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDefaultListMaxResults(int defaultListMaxResults)
|
||||||
|
{
|
||||||
|
this.defaultListMaxResults = defaultListMaxResults;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a Person with the given username
|
* Delete a Person with the given username
|
||||||
*
|
*
|
||||||
@@ -508,23 +509,27 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
*/
|
*/
|
||||||
public Scriptable getPeople(String filter, int maxResults)
|
public Scriptable getPeople(String filter, int maxResults)
|
||||||
{
|
{
|
||||||
|
boolean useCQ = false;
|
||||||
|
if (filter != null)
|
||||||
|
{
|
||||||
|
if (filter.endsWith(HINT_CQ_SUFFIX))
|
||||||
|
{
|
||||||
|
useCQ = true;
|
||||||
|
filter = filter.substring(0, filter.length()-HINT_CQ_SUFFIX.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Object[] people = null;
|
Object[] people = null;
|
||||||
|
|
||||||
// TODO - remove open-ended query (eg cutoff at default/configurable max, eg. 5000 people)
|
if ((maxResults <= 0) || (maxResults > defaultListMaxResults))
|
||||||
if (maxResults <= 0)
|
|
||||||
{
|
{
|
||||||
maxResults = Integer.MAX_VALUE;
|
// remove open-ended query (eg cutoff at default/configurable max, eg. 5000 people)
|
||||||
|
maxResults = defaultListMaxResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter == null || filter.length() == 0)
|
if ((filter == null || filter.length() == 0) || useCQ)
|
||||||
{
|
{
|
||||||
PagingRequest pagingRequest = new PagingRequest(maxResults, null);
|
people = getPeopleImplDB(filter, maxResults);
|
||||||
List<PersonInfo> persons = personService.getPeople(null, true, null, pagingRequest).getPage();
|
|
||||||
people = new Object[persons.size()];
|
|
||||||
for (int i=0; i<people.length; i++)
|
|
||||||
{
|
|
||||||
people[i] = persons.get(i).getNodeRef();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -536,27 +541,70 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
int propIndex = term.lastIndexOf(':');
|
int propIndex = term.lastIndexOf(':');
|
||||||
int wildPosition = term.indexOf('*');
|
int wildPosition = term.indexOf('*');
|
||||||
|
|
||||||
if ((t.countTokens() == 1) && (propIndex == -1) && ((wildPosition == -1) || (wildPosition == (term.length() - 1) )))
|
// simple filter - can use CQ if search fails
|
||||||
|
useCQ = ((t.countTokens() == 1) && (propIndex == -1) && ((wildPosition == -1) || (wildPosition == (term.length() - 1))));
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
people = getPeopleImplSearch(term, t, propIndex, maxResults);
|
||||||
|
}
|
||||||
|
catch (Throwable err)
|
||||||
|
{
|
||||||
|
if (useCQ)
|
||||||
|
{
|
||||||
|
// search unavailable and/or parser exception - try CQ instead
|
||||||
|
people = getPeopleImplDB(term, maxResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (people == null)
|
||||||
|
{
|
||||||
|
people = new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Context.getCurrentContext().newArray(getScope(), people);
|
||||||
|
}
|
||||||
|
|
||||||
|
// canned query
|
||||||
|
private Object[] getPeopleImplDB(String term, int maxResults)
|
||||||
|
{
|
||||||
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||||
|
Object[] people = null;
|
||||||
|
|
||||||
// simple non-FTS filter: firstname or lastname or username starting with term (ignoring case)
|
// simple non-FTS filter: firstname or lastname or username starting with term (ignoring case)
|
||||||
|
|
||||||
String propVal = term;
|
List<QName> filterProps = new ArrayList<QName>(3);
|
||||||
|
filterProps.add(ContentModel.PROP_FIRSTNAME);
|
||||||
|
filterProps.add(ContentModel.PROP_LASTNAME);
|
||||||
|
filterProps.add(ContentModel.PROP_USERNAME);
|
||||||
|
|
||||||
List<Pair<QName, String>> filterProps = new ArrayList<Pair<QName, String>>(3);
|
List<Pair<QName, Boolean>> sortProps = new ArrayList<Pair<QName, Boolean>>(1);
|
||||||
filterProps.add(new Pair<QName, String>(ContentModel.PROP_FIRSTNAME, propVal));
|
sortProps.add(new Pair<QName, Boolean>(ContentModel.PROP_USERNAME, true));
|
||||||
filterProps.add(new Pair<QName, String>(ContentModel.PROP_LASTNAME, propVal));
|
|
||||||
filterProps.add(new Pair<QName, String>(ContentModel.PROP_USERNAME, propVal));
|
|
||||||
|
|
||||||
PagingRequest pagingRequest = new PagingRequest(maxResults, null);
|
PagingRequest pagingRequest = new PagingRequest(maxResults, null);
|
||||||
List<PersonInfo> persons = personService.getPeople(filterProps, true, null, pagingRequest).getPage();
|
List<PersonInfo> persons = personService.getPeople(term, filterProps, sortProps, pagingRequest).getPage();
|
||||||
people = new Object[persons.size()];
|
people = new Object[persons.size()];
|
||||||
for (int i=0; i<people.length; i++)
|
for (int i=0; i<people.length; i++)
|
||||||
{
|
{
|
||||||
people[i] = persons.get(i).getNodeRef();
|
people[i] = persons.get(i).getNodeRef();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (start != null)
|
||||||
{
|
{
|
||||||
|
logger.debug("getPeople: cq - "+people.length+" items (in "+(System.currentTimeMillis()-start)+" msecs)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return people;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search query
|
||||||
|
private Object[] getPeopleImplSearch(String term, StringTokenizer t, int propIndex, int maxResults) throws Throwable
|
||||||
|
{
|
||||||
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||||
|
Object[] people = null;
|
||||||
|
|
||||||
SearchParameters params = new SearchParameters();
|
SearchParameters params = new SearchParameters();
|
||||||
params.addQueryTemplate("_PERSON", "|%firstName OR |%lastName OR |%userName");
|
params.addQueryTemplate("_PERSON", "|%firstName OR |%lastName OR |%userName");
|
||||||
params.setDefaultFieldName("_PERSON");
|
params.setDefaultFieldName("_PERSON");
|
||||||
@@ -665,13 +713,21 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
{
|
{
|
||||||
results = services.getSearchService().query(params);
|
results = services.getSearchService().query(params);
|
||||||
people = results.getNodeRefs().toArray();
|
people = results.getNodeRefs().toArray();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
logger.debug("getPeople: search - "+people.length+" items (in "+(System.currentTimeMillis()-start)+" msecs)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable err)
|
catch (Throwable err)
|
||||||
{
|
{
|
||||||
// hide query parse error from users
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
logger.debug("Failed to execute people search: " + query.toString(), err);
|
logger.debug("Failed to execute people search: " + query.toString(), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (results != null)
|
if (results != null)
|
||||||
@@ -679,16 +735,8 @@ public final class People extends BaseScopableProcessorExtension implements Init
|
|||||||
results.close();
|
results.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (people == null)
|
return people;
|
||||||
{
|
|
||||||
people = new Object[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Context.getCurrentContext().newArray(getScope(), people);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.person;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filterable/Sortable Person Entity
|
||||||
|
*
|
||||||
|
* Can be optionally filtered/sorted by (up to) three properties - note: sort applied in same order as filter properties (if sort order is not null for given property)
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public class FilterSortPersonEntity
|
||||||
|
{
|
||||||
|
private Long parentNodeId;
|
||||||
|
|
||||||
|
private Long prop1qnameId =null;
|
||||||
|
private Boolean sort1asc = null;
|
||||||
|
|
||||||
|
private Long prop2qnameId = null;
|
||||||
|
private Boolean sort2asc = null;
|
||||||
|
|
||||||
|
private Long prop3qnameId = null;
|
||||||
|
private Boolean sort3asc = null;
|
||||||
|
|
||||||
|
private String pattern;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor
|
||||||
|
*/
|
||||||
|
public FilterSortPersonEntity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getParentNodeId()
|
||||||
|
{
|
||||||
|
return parentNodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentNodeId(Long parentNodeId)
|
||||||
|
{
|
||||||
|
this.parentNodeId = parentNodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPattern()
|
||||||
|
{
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String escape(String s, char escapeChar)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int idx = -1;
|
||||||
|
int offset = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
idx = s.indexOf(escapeChar, offset);
|
||||||
|
if(idx != -1)
|
||||||
|
{
|
||||||
|
sb.append(s.substring(offset, idx));
|
||||||
|
sb.append("\\");
|
||||||
|
sb.append(escapeChar);
|
||||||
|
offset = idx + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(idx != -1);
|
||||||
|
sb.append(s.substring(offset));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPattern(String pattern)
|
||||||
|
{
|
||||||
|
if (pattern != null)
|
||||||
|
{
|
||||||
|
// escape the '%' character with '\' (standard SQL escape character)
|
||||||
|
//pattern = escape(pattern, '%');
|
||||||
|
|
||||||
|
// replace the wildcard character '*' with the one used in database queries i.e. '%'
|
||||||
|
this.pattern = pattern.replace('*', '%');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getProp1qnameId()
|
||||||
|
{
|
||||||
|
return prop1qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProp1qnameId(Long prop1qnameId)
|
||||||
|
{
|
||||||
|
this.prop1qnameId = prop1qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSort1asc()
|
||||||
|
{
|
||||||
|
return sort1asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSort1asc(Boolean sort1asc)
|
||||||
|
{
|
||||||
|
this.sort1asc = sort1asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getProp2qnameId()
|
||||||
|
{
|
||||||
|
return prop2qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProp2qnameId(Long prop2qnameId)
|
||||||
|
{
|
||||||
|
this.prop2qnameId = prop2qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSort2asc()
|
||||||
|
{
|
||||||
|
return sort2asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSort2asc(Boolean sort2asc)
|
||||||
|
{
|
||||||
|
this.sort2asc = sort2asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getProp3qnameId()
|
||||||
|
{
|
||||||
|
return prop3qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProp3qnameId(Long prop3qnameId)
|
||||||
|
{
|
||||||
|
this.prop3qnameId = prop3qnameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getSort3asc()
|
||||||
|
{
|
||||||
|
return sort3asc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSort3asc(Boolean sort3asc)
|
||||||
|
{
|
||||||
|
this.sort3asc = sort3asc;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.person;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.query.AbstractCannedQuery;
|
||||||
|
import org.alfresco.query.CannedQueryParameters;
|
||||||
|
import org.alfresco.query.CannedQuerySortDetails;
|
||||||
|
import org.alfresco.query.CannedQuerySortDetails.SortOrder;
|
||||||
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
|
import org.alfresco.repo.domain.query.CannedQueryDAO;
|
||||||
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
|
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetPeople canned query
|
||||||
|
*
|
||||||
|
* To get paged list of children of a parent node filtered by child type.
|
||||||
|
* Also optionally filtered and/or sorted by one or more properties (up to three).
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public class GetPeopleCannedQuery extends AbstractCannedQuery<NodeRef>
|
||||||
|
{
|
||||||
|
private Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
private static final String QUERY_NAMESPACE = "alfresco.query.people";
|
||||||
|
private static final String QUERY_SELECT_GET_PEOPLE = "select_GetPeopleCannedQuery";
|
||||||
|
|
||||||
|
public static final int MAX_FILTER_SORT_PROPS = 3;
|
||||||
|
|
||||||
|
private NodeDAO nodeDAO;
|
||||||
|
private QNameDAO qnameDAO;
|
||||||
|
private CannedQueryDAO cannedQueryDAO;
|
||||||
|
private TenantService tenantService;
|
||||||
|
|
||||||
|
public GetPeopleCannedQuery(
|
||||||
|
NodeDAO nodeDAO,
|
||||||
|
QNameDAO qnameDAO,
|
||||||
|
CannedQueryDAO cannedQueryDAO,
|
||||||
|
TenantService tenantService,
|
||||||
|
CannedQueryParameters params)
|
||||||
|
{
|
||||||
|
super(params);
|
||||||
|
|
||||||
|
this.nodeDAO = nodeDAO;
|
||||||
|
this.qnameDAO = qnameDAO;
|
||||||
|
this.cannedQueryDAO = cannedQueryDAO;
|
||||||
|
this.tenantService = tenantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<NodeRef> queryAndFilter(CannedQueryParameters parameters)
|
||||||
|
{
|
||||||
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||||
|
|
||||||
|
// Get parameters
|
||||||
|
GetPeopleCannedQueryParams paramBean = (GetPeopleCannedQueryParams)parameters.getParameterBean();
|
||||||
|
|
||||||
|
// Get parent node
|
||||||
|
NodeRef parentRef = paramBean.getParentRef();
|
||||||
|
ParameterCheck.mandatory("nodeRef", parentRef);
|
||||||
|
Pair<Long, NodeRef> nodePair = nodeDAO.getNodePair(parentRef);
|
||||||
|
if (nodePair == null)
|
||||||
|
{
|
||||||
|
throw new InvalidNodeRefException("Parent node does not exist: " + parentRef, parentRef);
|
||||||
|
}
|
||||||
|
Long parentNodeId = nodePair.getFirst();
|
||||||
|
|
||||||
|
// Set query params - note: currently using SortableChildEntity to hold (supplemental-) query params
|
||||||
|
FilterSortPersonEntity params = new FilterSortPersonEntity();
|
||||||
|
|
||||||
|
// Set parent node id
|
||||||
|
params.setParentNodeId(parentNodeId);
|
||||||
|
|
||||||
|
// Get filter details
|
||||||
|
final List<QName> filterProps = paramBean.getFilterProps();
|
||||||
|
|
||||||
|
// Get sort details
|
||||||
|
CannedQuerySortDetails sortDetails = parameters.getSortDetails();
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
final List<Pair<QName, SortOrder>> sortPairs = (List)sortDetails.getSortPairs();
|
||||||
|
|
||||||
|
String pattern = paramBean.getPattern();
|
||||||
|
if ((sortPairs.size() > 0) && ((pattern == null) || (pattern.equals(""))))
|
||||||
|
{
|
||||||
|
// note: although no pattern means no filtering required, we currently need to match all if sort required
|
||||||
|
pattern = "%";
|
||||||
|
}
|
||||||
|
else if ((! pattern.endsWith("%")) && (! pattern.endsWith("*")))
|
||||||
|
{
|
||||||
|
// implicit startsWith match
|
||||||
|
pattern = pattern + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set filter pattern
|
||||||
|
params.setPattern(pattern);
|
||||||
|
|
||||||
|
// Set sort / filter params
|
||||||
|
// Note - need to keep the sort properties in their requested order
|
||||||
|
List<QName> sortFilterProps = new ArrayList<QName>(MAX_FILTER_SORT_PROPS);
|
||||||
|
Map<QName, Boolean> sortAsc = new HashMap<QName, Boolean>(MAX_FILTER_SORT_PROPS);
|
||||||
|
|
||||||
|
// add sort props first
|
||||||
|
for (Pair<QName, SortOrder> sort : sortPairs)
|
||||||
|
{
|
||||||
|
QName sortQName = sort.getFirst();
|
||||||
|
if ((filterProps.size() > 0) && (! filterProps.contains(sortQName)))
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("GetPeople: cannot sort by a non-filter property: "+sortQName+" (filterStringProps="+filterProps+")");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! sortFilterProps.contains(sortQName))
|
||||||
|
{
|
||||||
|
sortFilterProps.add(sortQName);
|
||||||
|
sortAsc.put(sortQName, sort.getSecond().equals(SortOrder.ASCENDING));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add any additional filter props (not part of sort)
|
||||||
|
for (QName filterQName : filterProps)
|
||||||
|
{
|
||||||
|
if (! sortFilterProps.contains(filterQName))
|
||||||
|
{
|
||||||
|
sortFilterProps.add(filterQName);
|
||||||
|
sortAsc.put(filterQName, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int filterSortPropCnt = sortFilterProps.size();
|
||||||
|
|
||||||
|
if (filterSortPropCnt > MAX_FILTER_SORT_PROPS)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("GetPeople: exceeded maximum number filter/sort properties: (max="+MAX_FILTER_SORT_PROPS+", actual="+filterSortPropCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
filterSortPropCnt = setFilterSortParams(sortFilterProps, sortAsc, params);
|
||||||
|
|
||||||
|
// filtered and/or sorted - note: permissions not applicable for getPeople
|
||||||
|
final List<NodeRef> result = new ArrayList<NodeRef>(100);
|
||||||
|
final PersonQueryCallback c = new DefaultPersonQueryCallback(result);
|
||||||
|
PersonResultHandler resultHandler = new PersonResultHandler(c);
|
||||||
|
|
||||||
|
int offset = parameters.getPageDetails().getSkipResults();
|
||||||
|
int limit = parameters.getPageDetails().getPageSize();
|
||||||
|
if (limit != Integer.MAX_VALUE)
|
||||||
|
{
|
||||||
|
// to enable hasMore flag
|
||||||
|
limit++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cannedQueryDAO.executeQuery(QUERY_NAMESPACE, QUERY_SELECT_GET_PEOPLE, params, offset, limit, resultHandler);
|
||||||
|
resultHandler.done();
|
||||||
|
|
||||||
|
if (start != null)
|
||||||
|
{
|
||||||
|
logger.debug("Base query: "+result.size()+" in "+(System.currentTimeMillis()-start)+" msecs");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set filter/sort props (between 0 and 3)
|
||||||
|
private int setFilterSortParams(List<QName> filterSortProps, Map<QName, Boolean> sortAsc, FilterSortPersonEntity params)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
int propCnt = 0;
|
||||||
|
|
||||||
|
for (QName filterSortProp : filterSortProps)
|
||||||
|
{
|
||||||
|
Long sortQNameId = getQNameId(filterSortProp);
|
||||||
|
Boolean sortOrder = sortAsc.get(filterSortProp); // true = ascending, false = descending, null = unsorted
|
||||||
|
|
||||||
|
if (sortQNameId != null)
|
||||||
|
{
|
||||||
|
if (propCnt == 0)
|
||||||
|
{
|
||||||
|
params.setProp1qnameId(sortQNameId);
|
||||||
|
params.setSort1asc(sortOrder);
|
||||||
|
}
|
||||||
|
else if (propCnt == 1)
|
||||||
|
{
|
||||||
|
params.setProp2qnameId(sortQNameId);
|
||||||
|
params.setSort2asc(sortOrder);
|
||||||
|
}
|
||||||
|
else if (propCnt == 2)
|
||||||
|
{
|
||||||
|
params.setProp3qnameId(sortQNameId);
|
||||||
|
params.setSort3asc(sortOrder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// belts and braces
|
||||||
|
throw new AlfrescoRuntimeException("GetPeople: unexpected - cannot set sort parameter: "+cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
propCnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("Skipping filter/sort param - cannot find: "+filterSortProp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getQNameId(QName sortPropQName)
|
||||||
|
{
|
||||||
|
Pair<Long, QName> qnamePair = qnameDAO.getQName(sortPropQName);
|
||||||
|
return (qnamePair == null ? null : qnamePair.getFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isApplyPostQuerySorting()
|
||||||
|
{
|
||||||
|
// note: sorted as part of the query impl
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isApplyPostQueryPermissions()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isApplyPostQueryPaging()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Pair<Integer, Integer> getTotalResultCount(List<NodeRef> results)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface PersonQueryCallback
|
||||||
|
{
|
||||||
|
boolean handle(NodeRef personRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class DefaultPersonQueryCallback implements PersonQueryCallback
|
||||||
|
{
|
||||||
|
private List<NodeRef> children;
|
||||||
|
|
||||||
|
public DefaultPersonQueryCallback(final List<NodeRef> children)
|
||||||
|
{
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(NodeRef personRef)
|
||||||
|
{
|
||||||
|
children.add(tenantService.getBaseName(personRef));
|
||||||
|
|
||||||
|
// More results
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class PersonResultHandler implements CannedQueryDAO.ResultHandler<String>
|
||||||
|
{
|
||||||
|
private final PersonQueryCallback resultsCallback;
|
||||||
|
|
||||||
|
private PersonResultHandler(PersonQueryCallback resultsCallback)
|
||||||
|
{
|
||||||
|
this.resultsCallback = resultsCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleResult(String uuid)
|
||||||
|
{
|
||||||
|
// Call back
|
||||||
|
return resultsCallback.handle(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void done()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.person;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.query.AbstractCannedQueryFactory;
|
||||||
|
import org.alfresco.query.CannedQuery;
|
||||||
|
import org.alfresco.query.CannedQueryPageDetails;
|
||||||
|
import org.alfresco.query.CannedQueryParameters;
|
||||||
|
import org.alfresco.query.CannedQuerySortDetails;
|
||||||
|
import org.alfresco.query.CannedQuerySortDetails.SortOrder;
|
||||||
|
import org.alfresco.query.PagingRequest;
|
||||||
|
import org.alfresco.repo.domain.node.NodeDAO;
|
||||||
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
|
import org.alfresco.repo.domain.query.CannedQueryDAO;
|
||||||
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
import org.alfresco.util.PropertyCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetPeople canned query factory - to get paged list of people
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public class GetPeopleCannedQueryFactory extends AbstractCannedQueryFactory<NodeRef>
|
||||||
|
{
|
||||||
|
protected NodeDAO nodeDAO;
|
||||||
|
protected QNameDAO qnameDAO;
|
||||||
|
protected CannedQueryDAO cannedQueryDAO;
|
||||||
|
protected TenantService tenantService;
|
||||||
|
|
||||||
|
public void setNodeDAO(NodeDAO nodeDAO)
|
||||||
|
{
|
||||||
|
this.nodeDAO = nodeDAO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQnameDAO(QNameDAO qnameDAO)
|
||||||
|
{
|
||||||
|
this.qnameDAO = qnameDAO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCannedQueryDAO(CannedQueryDAO cannedQueryDAO)
|
||||||
|
{
|
||||||
|
this.cannedQueryDAO = cannedQueryDAO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantService(TenantService tenantService)
|
||||||
|
{
|
||||||
|
this.tenantService = tenantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CannedQuery<NodeRef> getCannedQuery(CannedQueryParameters parameters)
|
||||||
|
{
|
||||||
|
return (CannedQuery<NodeRef>) new GetPeopleCannedQuery(nodeDAO, qnameDAO, cannedQueryDAO, tenantService, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CannedQuery<NodeRef> getCannedQuery(NodeRef parentRef, String pattern, List<QName> filterProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("parentRef", parentRef);
|
||||||
|
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||||
|
|
||||||
|
int requestTotalCountMax = pagingRequest.getRequestTotalCountMax();
|
||||||
|
|
||||||
|
// specific query params - context (parent) and inclusive filters (property values)
|
||||||
|
GetPeopleCannedQueryParams paramBean = new GetPeopleCannedQueryParams(tenantService.getName(parentRef), filterProps, pattern);
|
||||||
|
|
||||||
|
// page details
|
||||||
|
CannedQueryPageDetails cqpd = new CannedQueryPageDetails(pagingRequest.getSkipCount(), pagingRequest.getMaxItems(), CannedQueryPageDetails.DEFAULT_PAGE_NUMBER, CannedQueryPageDetails.DEFAULT_PAGE_COUNT);
|
||||||
|
|
||||||
|
// sort details
|
||||||
|
CannedQuerySortDetails cqsd = null;
|
||||||
|
if (sortProps != null)
|
||||||
|
{
|
||||||
|
List<Pair<? extends Object, SortOrder>> sortPairs = new ArrayList<Pair<? extends Object, SortOrder>>(sortProps.size());
|
||||||
|
for (Pair<QName, Boolean> sortProp : sortProps)
|
||||||
|
{
|
||||||
|
sortPairs.add(new Pair<QName, SortOrder>(sortProp.getFirst(), (sortProp.getSecond() ? SortOrder.ASCENDING : SortOrder.DESCENDING)));
|
||||||
|
}
|
||||||
|
|
||||||
|
cqsd = new CannedQuerySortDetails(sortPairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create query params holder
|
||||||
|
CannedQueryParameters params = new CannedQueryParameters(paramBean, cqpd, cqsd, requestTotalCountMax, pagingRequest.getQueryExecutionId());
|
||||||
|
|
||||||
|
// return canned query instance
|
||||||
|
return getCannedQuery(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception
|
||||||
|
{
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
|
||||||
|
PropertyCheck.mandatory(this, "tenantService", tenantService);
|
||||||
|
PropertyCheck.mandatory(this, "nodeDAO", nodeDAO);
|
||||||
|
PropertyCheck.mandatory(this, "qnameDAO", qnameDAO);
|
||||||
|
PropertyCheck.mandatory(this, "cannedQueryDAO", cannedQueryDAO);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.security.person;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetPeople CQ parameters - for query context and filtering
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public class GetPeopleCannedQueryParams
|
||||||
|
{
|
||||||
|
private NodeRef parentRef;
|
||||||
|
private List<QName> filterProps = Collections.emptyList();
|
||||||
|
private String pattern = null;
|
||||||
|
|
||||||
|
public GetPeopleCannedQueryParams(
|
||||||
|
NodeRef parentRef,
|
||||||
|
List<QName> filterProps,
|
||||||
|
String pattern)
|
||||||
|
{
|
||||||
|
this.parentRef = parentRef;
|
||||||
|
if (filterProps != null) { this.filterProps = filterProps; }
|
||||||
|
|
||||||
|
this.pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeRef getParentRef()
|
||||||
|
{
|
||||||
|
return parentRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<QName> getFilterProps()
|
||||||
|
{
|
||||||
|
return filterProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPattern()
|
||||||
|
{
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,6 @@ package org.alfresco.repo.security.person;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -29,12 +28,10 @@ import java.util.LinkedHashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.query.CannedQuery;
|
|
||||||
import org.alfresco.query.CannedQueryFactory;
|
import org.alfresco.query.CannedQueryFactory;
|
||||||
import org.alfresco.query.CannedQueryResults;
|
import org.alfresco.query.CannedQueryResults;
|
||||||
import org.alfresco.query.PagingRequest;
|
import org.alfresco.query.PagingRequest;
|
||||||
@@ -81,9 +78,6 @@ import org.alfresco.service.cmr.repository.NodeService;
|
|||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.cmr.repository.TemplateService;
|
import org.alfresco.service.cmr.repository.TemplateService;
|
||||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
import org.alfresco.service.cmr.search.LimitBy;
|
|
||||||
import org.alfresco.service.cmr.search.ResultSet;
|
|
||||||
import org.alfresco.service.cmr.search.SearchParameters;
|
|
||||||
import org.alfresco.service.cmr.search.SearchService;
|
import org.alfresco.service.cmr.search.SearchService;
|
||||||
import org.alfresco.service.cmr.security.AuthorityService;
|
import org.alfresco.service.cmr.security.AuthorityService;
|
||||||
import org.alfresco.service.cmr.security.AuthorityType;
|
import org.alfresco.service.cmr.security.AuthorityType;
|
||||||
@@ -115,7 +109,8 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
|
|||||||
{
|
{
|
||||||
private static Log logger = LogFactory.getLog(PersonServiceImpl.class);
|
private static Log logger = LogFactory.getLog(PersonServiceImpl.class);
|
||||||
|
|
||||||
private static final String CANNED_QUERY_PEOPLE_LIST = "peopleGetChildrenCannedQueryFactory";
|
private static final String CANNED_QUERY_PEOPLE_LIST = "getPeopleCannedQueryFactory";
|
||||||
|
private static final String CANNED_QUERY_PEOPLE_LIST_DEPRECATED = "peopleGetChildrenCannedQueryFactory";
|
||||||
|
|
||||||
private static final String DELETE = "DELETE";
|
private static final String DELETE = "DELETE";
|
||||||
private static final String SPLIT = "SPLIT";
|
private static final String SPLIT = "SPLIT";
|
||||||
@@ -1190,37 +1185,8 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
|
|||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private List<FilterProp> getFilterProps(List<Pair<QName, String>> stringPropFilters, boolean filterIgnoreCase)
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public PagingResults<PersonInfo> getPeople(List<Pair<QName, String>> stringPropFilters, boolean filterIgnoreCase, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
|
|
||||||
{
|
{
|
||||||
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
|
||||||
|
|
||||||
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
|
||||||
|
|
||||||
// TODO Remove this ALF-14127 hot fix code (calling nonCannedGetPeopleQuery(...) once this canned query does not fetch all rows from the database,
|
|
||||||
// which is very slow when there are a lot of users. 10,000 user takes about 4 seconds. The customer has 90,000.
|
|
||||||
CannedQueryResults<NodeRef> cqResults = null;
|
|
||||||
String searchValue = null;
|
|
||||||
if (filterIgnoreCase && pagingRequest != null && pagingRequest.getQueryExecutionId() == null && pagingRequest.getSkipCount() == 0)
|
|
||||||
{
|
|
||||||
searchValue = getSearchOnNameValue(stringPropFilters);
|
|
||||||
}
|
|
||||||
if (searchValue != null)
|
|
||||||
{
|
|
||||||
cqResults = nonCannedGetPeopleQuery(searchValue, pagingRequest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NodeRef contextNodeRef = getPeopleContainer();
|
|
||||||
|
|
||||||
Set<QName> childTypeQNames = new HashSet<QName>(1);
|
|
||||||
childTypeQNames.add(ContentModel.TYPE_PERSON);
|
|
||||||
|
|
||||||
// get canned query
|
|
||||||
GetChildrenCannedQueryFactory getChildrenCannedQueryFactory = (GetChildrenCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_PEOPLE_LIST);
|
|
||||||
|
|
||||||
List<FilterProp> filterProps = null;
|
List<FilterProp> filterProps = null;
|
||||||
if (stringPropFilters != null)
|
if (stringPropFilters != null)
|
||||||
{
|
{
|
||||||
@@ -1244,17 +1210,40 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetChildrenCannedQuery cq = (GetChildrenCannedQuery)getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, null, null, childTypeQNames, filterProps, sortProps, pagingRequest);
|
return filterProps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public PagingResults<PersonInfo> getPeople(String pattern, List<QName> filterStringProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
|
||||||
|
{
|
||||||
|
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||||
|
|
||||||
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||||
|
|
||||||
|
CannedQueryResults<NodeRef> cqResults = null;
|
||||||
|
|
||||||
|
NodeRef contextNodeRef = getPeopleContainer();
|
||||||
|
|
||||||
|
// get canned query
|
||||||
|
GetPeopleCannedQueryFactory getPeopleCannedQueryFactory = (GetPeopleCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_PEOPLE_LIST);
|
||||||
|
|
||||||
|
GetPeopleCannedQuery cq = (GetPeopleCannedQuery)getPeopleCannedQueryFactory.getCannedQuery(contextNodeRef, pattern, filterStringProps, sortProps, pagingRequest);
|
||||||
|
|
||||||
// execute canned query
|
// execute canned query
|
||||||
cqResults = cq.execute();
|
cqResults = cq.execute();
|
||||||
}
|
|
||||||
|
|
||||||
final CannedQueryResults<NodeRef> results = cqResults;
|
final CannedQueryResults<NodeRef> results = cqResults;
|
||||||
final List<NodeRef> nodeRefs;
|
List<NodeRef> nodeRefs;
|
||||||
if (results.getPageCount() > 0)
|
if (results.getPageCount() > 0)
|
||||||
{
|
{
|
||||||
nodeRefs = results.getPages().get(0);
|
nodeRefs = results.getPages().get(0);
|
||||||
|
if (nodeRefs.size() > pagingRequest.getMaxItems())
|
||||||
|
{
|
||||||
|
// eg. since hasMoreItems added one (for a pre-paged result)
|
||||||
|
nodeRefs = nodeRefs.subList(0, pagingRequest.getMaxItems());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1285,8 +1274,8 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
"getPeople: "+cnt+" items in "+(System.currentTimeMillis()-start)+" msecs " +
|
"getPeople: "+cnt+" items in "+(System.currentTimeMillis()-start)+" msecs " +
|
||||||
"[pageNum="+pageNum+",skip="+skipCount+",max="+maxItems+",hasMorePages="+hasMoreItems+
|
"[pageNum="+pageNum+",skip="+skipCount+",max="+maxItems+",hasMorePages="+hasMoreItems+
|
||||||
",totalCount="+totalCount+",filters="+stringPropFilters+
|
",totalCount="+totalCount+",pattern="+pattern+",filterStringProps="+filterStringProps+
|
||||||
",filtersIgnoreCase="+filterIgnoreCase+"]");
|
",sortProps="+sortProps+"]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1326,255 +1315,104 @@ public class PersonServiceImpl extends TransactionListenerAdapter implements Per
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the search is on first, last and user name only with the same value, return that value,
|
* {@inheritDoc}
|
||||||
* otherwise return null.
|
|
||||||
*/
|
*/
|
||||||
// TODO Remove this ALF-14127 hot fix code once this canned query does not fetch all rows from the database.
|
public PagingResults<PersonInfo> getPeople(List<Pair<QName, String>> stringPropFilters, boolean filterIgnoreCase, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
|
||||||
private String getSearchOnNameValue(List<Pair<QName, String>> stringPropFilters)
|
|
||||||
{
|
{
|
||||||
String filter = null;
|
ParameterCheck.mandatory("pagingRequest", pagingRequest);
|
||||||
if (stringPropFilters != null && stringPropFilters.size() == 3)
|
|
||||||
{
|
|
||||||
// Does not check we don't have duplicates.
|
|
||||||
for (int i=0; i < 3; i++)
|
|
||||||
{
|
|
||||||
Pair<QName, String> pair = stringPropFilters.get(i);
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
filter = pair.getSecond().trim();
|
|
||||||
if (filter == null || filter.length() == 0)
|
|
||||||
{
|
|
||||||
filter = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((i != 0 && !filter.equals(pair.getSecond().trim()) || !NAME_SEARCH_NAMES.contains(pair.getFirst())))
|
|
||||||
{
|
|
||||||
filter = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Remove this ALF-14127 hot fix code once this canned query does not fetch all rows from the database.
|
|
||||||
private static final List<QName> NAME_SEARCH_NAMES = Arrays.asList(new QName[] {
|
|
||||||
ContentModel.PROP_FIRSTNAME, ContentModel.PROP_LASTNAME, ContentModel.PROP_USERNAME});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use Solr search based on code in org.alfresco.repo.jscript.People.getPeople(String, int)
|
|
||||||
*/
|
|
||||||
// TODO Remove this ALF-14127 hot fix code once this canned query does not fetch all rows from the database.
|
|
||||||
private CannedQueryResults<NodeRef> nonCannedGetPeopleQuery(String filter, PagingRequest pagingRequest)
|
|
||||||
{
|
|
||||||
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
Long start = (logger.isDebugEnabled() ? System.currentTimeMillis() : null);
|
||||||
int maxResults = pagingRequest != null ? pagingRequest.getMaxItems() : Integer.MAX_VALUE;
|
|
||||||
if (maxResults <= 0)
|
CannedQueryResults<NodeRef> cqResults = null;
|
||||||
|
|
||||||
|
NodeRef contextNodeRef = getPeopleContainer();
|
||||||
|
|
||||||
|
Set<QName> childTypeQNames = new HashSet<QName>(1);
|
||||||
|
childTypeQNames.add(ContentModel.TYPE_PERSON);
|
||||||
|
|
||||||
|
// get canned query
|
||||||
|
GetChildrenCannedQueryFactory getChildrenCannedQueryFactory = (GetChildrenCannedQueryFactory)cannedQueryRegistry.getNamedObject(CANNED_QUERY_PEOPLE_LIST_DEPRECATED);
|
||||||
|
|
||||||
|
List<FilterProp> filterProps = getFilterProps(stringPropFilters, filterIgnoreCase);
|
||||||
|
|
||||||
|
GetChildrenCannedQuery cq = (GetChildrenCannedQuery)getChildrenCannedQueryFactory.getCannedQuery(contextNodeRef, null, null, childTypeQNames, filterProps, sortProps, pagingRequest);
|
||||||
|
|
||||||
|
// execute canned query
|
||||||
|
cqResults = cq.execute();
|
||||||
|
|
||||||
|
final CannedQueryResults<NodeRef> results = cqResults;
|
||||||
|
final List<NodeRef> nodeRefs;
|
||||||
|
if (results.getPageCount() > 0)
|
||||||
{
|
{
|
||||||
maxResults = Integer.MAX_VALUE;
|
nodeRefs = results.getPages().get(0);
|
||||||
}
|
|
||||||
|
|
||||||
String term = filter.replace("\\", "").replace("\"", "");
|
|
||||||
StringTokenizer t = new StringTokenizer(term, " ");
|
|
||||||
int propIndex = term.indexOf(':');
|
|
||||||
|
|
||||||
SearchParameters params = new SearchParameters();
|
|
||||||
params.addQueryTemplate("_PERSON", "|%firstName OR |%lastName OR |%userName");
|
|
||||||
params.setDefaultFieldName("_PERSON");
|
|
||||||
|
|
||||||
StringBuilder query = new StringBuilder(256);
|
|
||||||
|
|
||||||
query.append("TYPE:\"").append(ContentModel.TYPE_PERSON).append("\" AND (");
|
|
||||||
|
|
||||||
if (t.countTokens() == 1)
|
|
||||||
{
|
|
||||||
// single word with no field will go against _PERSON and expand
|
|
||||||
|
|
||||||
// fts-alfresco property search i.e. location:"maidenhead"
|
|
||||||
query.append(term.substring(0, propIndex + 1)).append('"')
|
|
||||||
.append(term.substring(propIndex + 1));
|
|
||||||
if (propIndex > 0)
|
|
||||||
{
|
|
||||||
query.append('"');
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
query.append("*\"");
|
nodeRefs = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set total count
|
||||||
|
final Pair<Integer, Integer> totalCount;
|
||||||
|
if (pagingRequest.getRequestTotalCountMax() > 0)
|
||||||
|
{
|
||||||
|
totalCount = results.getTotalResultCount();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// scan for non-fts-alfresco property search tokens
|
totalCount = null;
|
||||||
int nonFtsTokens = 0;
|
|
||||||
while (t.hasMoreTokens())
|
|
||||||
{
|
|
||||||
if (t.nextToken().indexOf(':') == -1)
|
|
||||||
nonFtsTokens++;
|
|
||||||
}
|
|
||||||
t = new StringTokenizer(term, " ");
|
|
||||||
|
|
||||||
// multiple terms supplied - look for first and second name etc.
|
|
||||||
// assume first term is first name, any more are second i.e.
|
|
||||||
// "Fraun van de Wiels"
|
|
||||||
// also allow fts-alfresco property search to reduce results
|
|
||||||
params.setDefaultOperator(SearchParameters.Operator.AND);
|
|
||||||
boolean firstToken = true;
|
|
||||||
boolean tokenSurname = false;
|
|
||||||
boolean propertySearch = false;
|
|
||||||
while (t.hasMoreTokens())
|
|
||||||
{
|
|
||||||
term = t.nextToken();
|
|
||||||
if (!propertySearch && term.indexOf(':') == -1)
|
|
||||||
{
|
|
||||||
if (nonFtsTokens == 1)
|
|
||||||
{
|
|
||||||
// simple search: first name, last name and username
|
|
||||||
// starting with term
|
|
||||||
query.append("_PERSON:\"");
|
|
||||||
query.append(term);
|
|
||||||
query.append("*\" ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (firstToken)
|
|
||||||
{
|
|
||||||
query.append("firstName:\"");
|
|
||||||
query.append(term);
|
|
||||||
query.append("*\" ");
|
|
||||||
|
|
||||||
firstToken = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tokenSurname)
|
|
||||||
{
|
|
||||||
query.append("OR ");
|
|
||||||
}
|
|
||||||
query.append("lastName:\"");
|
|
||||||
query.append(term);
|
|
||||||
query.append("*\" ");
|
|
||||||
|
|
||||||
tokenSurname = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// fts-alfresco property search i.e. "location:maidenhead"
|
|
||||||
propIndex = term.indexOf(':');
|
|
||||||
query.append(term.substring(0, propIndex + 1)).append('"')
|
|
||||||
.append(term.substring(propIndex + 1)).append('"');
|
|
||||||
|
|
||||||
propertySearch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
query.append(")");
|
|
||||||
|
|
||||||
// define the search parameters
|
|
||||||
params.setLanguage(SearchService.LANGUAGE_FTS_ALFRESCO);
|
|
||||||
params.addStore(this.storeRef);
|
|
||||||
params.setQuery(query.toString());
|
|
||||||
if (maxResults > 0)
|
|
||||||
{
|
|
||||||
params.setLimitBy(LimitBy.FINAL_SIZE);
|
|
||||||
params.setLimit(maxResults);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultSet results = null;
|
if (start != null)
|
||||||
List<NodeRef> resultNodeRefs = null;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
results = searchService.query(params);
|
int cnt = results.getPagedResultCount();
|
||||||
resultNodeRefs = results.getNodeRefs();
|
int skipCount = pagingRequest.getSkipCount();
|
||||||
}
|
int maxItems = pagingRequest.getMaxItems();
|
||||||
catch (Throwable err)
|
boolean hasMoreItems = results.hasMoreItems();
|
||||||
{
|
int pageNum = (skipCount / maxItems) + 1;
|
||||||
resultNodeRefs = Collections.emptyList();
|
|
||||||
|
|
||||||
// hide query parse error from users
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("Failed to execute people search: " + query.toString(), err);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
{
|
||||||
if (results != null)
|
logger.debug(
|
||||||
{
|
"getPeople: "+cnt+" items in "+(System.currentTimeMillis()-start)+" msecs " +
|
||||||
results.close();
|
"[pageNum="+pageNum+",skip="+skipCount+",max="+maxItems+",hasMorePages="+hasMoreItems+
|
||||||
|
",totalCount="+totalCount+",filters="+stringPropFilters+
|
||||||
|
",filtersIgnoreCase="+filterIgnoreCase+",sortProps="+sortProps+"]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn NodeRefs into a single page of results.
|
final List<PersonInfo> personInfos = new ArrayList<PersonInfo>(nodeRefs.size());
|
||||||
final List<NodeRef> nodRefs = resultNodeRefs;
|
for (NodeRef nodeRef : nodeRefs)
|
||||||
CannedQueryResults<NodeRef> cqResults = new CannedQueryResults<NodeRef>()
|
|
||||||
{
|
{
|
||||||
@Override
|
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||||
public CannedQuery<NodeRef> getOriginatingQuery()
|
personInfos.add(new PersonInfo(nodeRef,
|
||||||
{
|
(String)props.get(ContentModel.PROP_USERNAME),
|
||||||
return null;
|
(String)props.get(ContentModel.PROP_FIRSTNAME),
|
||||||
|
(String)props.get(ContentModel.PROP_LASTNAME)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new PagingResults<PersonInfo>()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public String getQueryExecutionId()
|
public String getQueryExecutionId()
|
||||||
{
|
{
|
||||||
return null;
|
return results.getQueryExecutionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<Integer, Integer> getTotalResultCount()
|
public List<PersonInfo> getPage()
|
||||||
{
|
{
|
||||||
int size = nodRefs.size();
|
return personInfos;
|
||||||
return new Pair<Integer, Integer>(size, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPagedResultCount()
|
|
||||||
{
|
|
||||||
return nodRefs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPageCount()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeRef getSingleResult()
|
|
||||||
{
|
|
||||||
if (nodRefs.size() != 1)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"There must be exactly one page of one result available.");
|
|
||||||
}
|
|
||||||
return nodRefs.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<NodeRef> getPage()
|
|
||||||
{
|
|
||||||
return nodRefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<List<NodeRef>> getPages()
|
|
||||||
{
|
|
||||||
return Collections.singletonList(getPage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMoreItems()
|
public boolean hasMoreItems()
|
||||||
{
|
{
|
||||||
return false;
|
return results.hasMoreItems();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Pair<Integer, Integer> getTotalResultCount()
|
||||||
|
{
|
||||||
|
return totalCount;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("nonCannedGetPeopleQuery(\""+filter+"\", "+maxResults+") "+cqResults.getTotalResultCount()+" in "+(System.currentTimeMillis()-start)+" msecs ");
|
|
||||||
}
|
|
||||||
return cqResults;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -560,7 +560,6 @@ public class PersonTest extends TestCase
|
|||||||
|
|
||||||
personService.deletePerson("Derek");
|
personService.deletePerson("Derek");
|
||||||
assertEquals(2, getPeopleCount());
|
assertEquals(2, getPeopleCount());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPeopleFiltering()
|
public void testPeopleFiltering()
|
||||||
@@ -581,6 +580,113 @@ public class PersonTest extends TestCase
|
|||||||
|
|
||||||
PagingRequest pr = new PagingRequest(100, null);
|
PagingRequest pr = new PagingRequest(100, null);
|
||||||
|
|
||||||
|
List<QName> filters = new ArrayList<QName>(4);
|
||||||
|
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
assertEquals(2, personService.getPeople("y", filters, null, pr).getPage().size());
|
||||||
|
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
filters.add(ContentModel.PROP_FIRSTNAME);
|
||||||
|
filters.add(ContentModel.PROP_LASTNAME);
|
||||||
|
assertEquals(3, personService.getPeople("b", filters, null, pr).getPage().size());
|
||||||
|
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
assertEquals(2, personService.getPeople("A", filters, null, pr).getPage().size()); // includes "admin"
|
||||||
|
|
||||||
|
personService.deletePerson("aa");
|
||||||
|
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
assertEquals(1, personService.getPeople("a", filters, null, pr).getPage().size()); // includes "admin"
|
||||||
|
|
||||||
|
// a* is the same as a
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
assertEquals(1, personService.getPeople("a*", filters, null, pr).getPage().size()); // includes "admin"
|
||||||
|
|
||||||
|
// * means everyone
|
||||||
|
filters.clear();
|
||||||
|
filters.add(ContentModel.PROP_USERNAME);
|
||||||
|
assertEquals(5, getPeopleCount());
|
||||||
|
assertEquals(5, personService.getPeople("*", filters, null, pr).getPage().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPeopleSortingPaging()
|
||||||
|
{
|
||||||
|
personService.setCreateMissingPeople(false);
|
||||||
|
|
||||||
|
assertEquals(2, getPeopleCount());
|
||||||
|
|
||||||
|
NodeRef p1 = personService.getPerson(AuthenticationUtil.getAdminUserName()); // admin - by default
|
||||||
|
NodeRef p2 = personService.getPerson(AuthenticationUtil.getGuestUserName()); // guest - by default
|
||||||
|
|
||||||
|
NodeRef p3 = personService.createPerson(createDefaultProperties("aa", "Aa", "Aa", "aa@aa", "alfresco", rootNodeRef));
|
||||||
|
NodeRef p4 = personService.createPerson(createDefaultProperties("cc", "Cc", "Cc", "cc@cc", "alfresco", rootNodeRef));
|
||||||
|
NodeRef p5 = personService.createPerson(createDefaultProperties("hh", "Hh", "Hh", "hh@hh", "alfresco", rootNodeRef));
|
||||||
|
NodeRef p6 = personService.createPerson(createDefaultProperties("bb", "Bb", "Bb", "bb@bb", "alfresco", rootNodeRef));
|
||||||
|
NodeRef p7 = personService.createPerson(createDefaultProperties("dd", "Dd", "Dd", "dd@dd", "alfresco", rootNodeRef));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assertEquals(7, getPeopleCount());
|
||||||
|
|
||||||
|
List<Pair<QName, Boolean>> sort = new ArrayList<Pair<QName, Boolean>>(1);
|
||||||
|
sort.add(new Pair<QName,Boolean>(ContentModel.PROP_USERNAME, true));
|
||||||
|
|
||||||
|
// page 1
|
||||||
|
PagingRequest pr = new PagingRequest(0, 2, null);
|
||||||
|
PagingResults<PersonInfo> ppr = personService.getPeople(null, null, sort, pr);
|
||||||
|
List<PersonInfo> results = ppr.getPage();
|
||||||
|
assertEquals(2, results.size());
|
||||||
|
assertEquals(p3, results.get(0).getNodeRef());
|
||||||
|
assertEquals(p1, results.get(1).getNodeRef());
|
||||||
|
|
||||||
|
// page 2
|
||||||
|
pr = new PagingRequest(2, 2, null);
|
||||||
|
ppr = personService.getPeople(null, null, sort, pr);
|
||||||
|
results = ppr.getPage();
|
||||||
|
assertEquals(2, results.size());
|
||||||
|
assertEquals(p6, results.get(0).getNodeRef());
|
||||||
|
assertEquals(p4, results.get(1).getNodeRef());
|
||||||
|
|
||||||
|
// page 3
|
||||||
|
pr = new PagingRequest(4, 2, null);
|
||||||
|
ppr = personService.getPeople(null, null, sort, pr);
|
||||||
|
results = ppr.getPage();
|
||||||
|
assertEquals(2, results.size());
|
||||||
|
assertEquals(p7, results.get(0).getNodeRef());
|
||||||
|
assertEquals(p2, results.get(1).getNodeRef());
|
||||||
|
|
||||||
|
// page 4
|
||||||
|
pr = new PagingRequest(6, 2, null);
|
||||||
|
ppr = personService.getPeople(null, null, sort, pr);
|
||||||
|
results = ppr.getPage();
|
||||||
|
assertEquals(1, results.size());
|
||||||
|
assertEquals(p5, results.get(0).getNodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: this test can be removed as and when we remove the deprecated "getPeople" impl
|
||||||
|
public void testPeopleFiltering_deprecatedCQ_via_getChildren()
|
||||||
|
{
|
||||||
|
personService.setCreateMissingPeople(false);
|
||||||
|
|
||||||
|
assertEquals(2, getPeopleCount());
|
||||||
|
|
||||||
|
checkPeopleContain(AuthenticationUtil.getAdminUserName());
|
||||||
|
checkPeopleContain(AuthenticationUtil.getGuestUserName());
|
||||||
|
|
||||||
|
personService.createPerson(createDefaultProperties("aa", "Aa", "Aa", "aa@aa", "alfresco", rootNodeRef));
|
||||||
|
personService.createPerson(createDefaultProperties("bc", "c", "C", "bc@bc", "alfresco", rootNodeRef));
|
||||||
|
personService.createPerson(createDefaultProperties("yy", "B", "D", "yy@yy", "alfresco", rootNodeRef));
|
||||||
|
personService.createPerson(createDefaultProperties("Yz", "yz", "B", "yz@yz", "alfresco", rootNodeRef));
|
||||||
|
|
||||||
|
assertEquals(6, getPeopleCount());
|
||||||
|
|
||||||
|
PagingRequest pr = new PagingRequest(100, null);
|
||||||
|
|
||||||
List<Pair<QName, String>> filters = new ArrayList<Pair<QName, String>>(4);
|
List<Pair<QName, String>> filters = new ArrayList<Pair<QName, String>>(4);
|
||||||
|
|
||||||
filters.clear();
|
filters.clear();
|
||||||
@@ -618,7 +724,8 @@ public class PersonTest extends TestCase
|
|||||||
assertEquals(5, personService.getPeople(filters, true, null, pr).getPage().size());
|
assertEquals(5, personService.getPeople(filters, true, null, pr).getPage().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPeopleSortingPaging()
|
// note: this test can be removed as and when we remove the deprecated "getPeople" impl
|
||||||
|
public void testPeopleSortingPaging_deprecatedCQ_via_getChildren()
|
||||||
{
|
{
|
||||||
personService.setCreateMissingPeople(false);
|
personService.setCreateMissingPeople(false);
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||||
*
|
*
|
||||||
* This file is part of Alfresco
|
* This file is part of Alfresco
|
||||||
*
|
*
|
||||||
@@ -274,7 +274,25 @@ public interface PersonService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get paged list of people optionally filtered and/or sorted
|
* Get paged list of people optionally filtered and/or sorted
|
||||||
|
*
|
||||||
|
* Note: the pattern is applied to filter props (0 to 3) as startsWithIgnoreCase, which are OR'ed together, for example: cm:userName or cm:firstName or cm:lastName
|
||||||
|
*
|
||||||
|
* @param pattern pattern to apply to filter props - "startsWith" and "ignoreCase"
|
||||||
|
* @param filterProps list of filter properties (these are OR'ed)
|
||||||
|
* @param sortProps sort property, eg. cm:username ascending
|
||||||
|
* @param pagingRequest skip, max + optional query execution id
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @author janv
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
@Auditable(parameters = {"pattern", "filterProps", "sortProps", "pagingRequest"})
|
||||||
|
public PagingResults<PersonInfo> getPeople(String pattern, List<QName> filterProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get paged list of people optionally filtered and/or sorted
|
||||||
|
*
|
||||||
* @param filterProps list of filter properties (with "startsWith" values), eg. cm:username "al" might match "alex", "alice", ...
|
* @param filterProps list of filter properties (with "startsWith" values), eg. cm:username "al" might match "alex", "alice", ...
|
||||||
* @param filterIgnoreCase true to ignore case when filtering, false to be case-sensitive when filtering
|
* @param filterIgnoreCase true to ignore case when filtering, false to be case-sensitive when filtering
|
||||||
* @param sortProps sort property, eg. cm:username ascending
|
* @param sortProps sort property, eg. cm:username ascending
|
||||||
@@ -282,6 +300,7 @@ public interface PersonService
|
|||||||
*
|
*
|
||||||
* @author janv
|
* @author janv
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
* @deprecated see getPeople(String pattern, List<QName> filterProps, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest)
|
||||||
*/
|
*/
|
||||||
@Auditable(parameters = {"stringPropFilters", "filterIgnoreCase", "sortProps", "pagingRequest"})
|
@Auditable(parameters = {"stringPropFilters", "filterIgnoreCase", "sortProps", "pagingRequest"})
|
||||||
public PagingResults<PersonInfo> getPeople(List<Pair<QName,String>> stringPropFilters, boolean filterIgnoreCase, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest);
|
public PagingResults<PersonInfo> getPeople(List<Pair<QName,String>> stringPropFilters, boolean filterIgnoreCase, List<Pair<QName, Boolean>> sortProps, PagingRequest pagingRequest);
|
||||||
|
Reference in New Issue
Block a user