001
014
015 package com.liferay.portlet.usersadmin.util;
016
017 import com.liferay.portal.NoSuchContactException;
018 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.search.BaseIndexer;
023 import com.liferay.portal.kernel.search.BooleanClauseOccur;
024 import com.liferay.portal.kernel.search.BooleanQuery;
025 import com.liferay.portal.kernel.search.Document;
026 import com.liferay.portal.kernel.search.Field;
027 import com.liferay.portal.kernel.search.Indexer;
028 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
029 import com.liferay.portal.kernel.search.SearchContext;
030 import com.liferay.portal.kernel.search.SearchEngineUtil;
031 import com.liferay.portal.kernel.search.Summary;
032 import com.liferay.portal.kernel.search.filter.BooleanFilter;
033 import com.liferay.portal.kernel.search.filter.TermsFilter;
034 import com.liferay.portal.kernel.spring.osgi.OSGiBeanProperties;
035 import com.liferay.portal.kernel.util.ArrayUtil;
036 import com.liferay.portal.kernel.util.GetterUtil;
037 import com.liferay.portal.kernel.util.Validator;
038 import com.liferay.portal.kernel.workflow.WorkflowConstants;
039 import com.liferay.portal.model.Contact;
040 import com.liferay.portal.model.Organization;
041 import com.liferay.portal.model.User;
042 import com.liferay.portal.model.impl.ContactImpl;
043 import com.liferay.portal.security.auth.FullNameGenerator;
044 import com.liferay.portal.security.auth.FullNameGeneratorFactory;
045 import com.liferay.portal.service.OrganizationLocalServiceUtil;
046 import com.liferay.portal.service.UserLocalServiceUtil;
047 import com.liferay.portal.util.PropsValues;
048
049 import java.util.ArrayList;
050 import java.util.Collection;
051 import java.util.HashMap;
052 import java.util.HashSet;
053 import java.util.LinkedHashMap;
054 import java.util.Locale;
055 import java.util.Map;
056 import java.util.Set;
057
058 import javax.portlet.PortletRequest;
059 import javax.portlet.PortletResponse;
060
061
066 @OSGiBeanProperties
067 public class UserIndexer extends BaseIndexer {
068
069 public static final String CLASS_NAME = User.class.getName();
070
071 public static long getUserId(Document document) {
072 return GetterUtil.getLong(document.get(Field.USER_ID));
073 }
074
075 public UserIndexer() {
076 setCommitImmediately(true);
077 setDefaultSelectedFieldNames(
078 Field.ASSET_TAG_NAMES, Field.COMPANY_ID, Field.ENTRY_CLASS_NAME,
079 Field.ENTRY_CLASS_PK, Field.GROUP_ID, Field.MODIFIED_DATE,
080 Field.SCOPE_GROUP_ID, Field.UID, Field.USER_ID);
081 setIndexerEnabled(PropsValues.USERS_INDEXER_ENABLED);
082 setPermissionAware(true);
083 setStagingAware(false);
084 }
085
086 @Override
087 public String getClassName() {
088 return CLASS_NAME;
089 }
090
091 @Override
092 public void postProcessContextBooleanFilter(
093 BooleanFilter contextBooleanFilter, SearchContext searchContext)
094 throws Exception {
095
096 int status = GetterUtil.getInteger(
097 searchContext.getAttribute(Field.STATUS),
098 WorkflowConstants.STATUS_APPROVED);
099
100 if (status != WorkflowConstants.STATUS_ANY) {
101 contextBooleanFilter.addRequiredTerm(Field.STATUS, status);
102 }
103
104 LinkedHashMap<String, Object> params =
105 (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
106
107 if (params == null) {
108 return;
109 }
110
111 for (Map.Entry<String, Object> entry : params.entrySet()) {
112 String key = entry.getKey();
113 Object value = entry.getValue();
114
115 if (value == null) {
116 continue;
117 }
118
119 Class<?> clazz = value.getClass();
120
121 if (clazz.isArray()) {
122 Object[] values = (Object[])value;
123
124 if (values.length == 0) {
125 continue;
126 }
127 }
128
129 addContextQueryParams(
130 contextBooleanFilter, searchContext, key, value);
131 }
132 }
133
134 @Override
135 public void postProcessSearchQuery(
136 BooleanQuery searchQuery, BooleanFilter fullQueryBooleanFilter,
137 SearchContext searchContext)
138 throws Exception {
139
140 addSearchTerm(searchQuery, searchContext, "city", false);
141 addSearchTerm(searchQuery, searchContext, "country", false);
142 addSearchTerm(searchQuery, searchContext, "emailAddress", false);
143 addSearchTerm(searchQuery, searchContext, "firstName", false);
144 addSearchTerm(searchQuery, searchContext, "fullName", false);
145 addSearchTerm(searchQuery, searchContext, "lastName", false);
146 addSearchTerm(searchQuery, searchContext, "middleName", false);
147 addSearchTerm(searchQuery, searchContext, "region", false);
148 addSearchTerm(searchQuery, searchContext, "screenName", false);
149 addSearchTerm(searchQuery, searchContext, "street", false);
150 addSearchTerm(searchQuery, searchContext, "zip", false);
151
152 LinkedHashMap<String, Object> params =
153 (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
154
155 if (params != null) {
156 String expandoAttributes = (String)params.get("expandoAttributes");
157
158 if (Validator.isNotNull(expandoAttributes)) {
159 addSearchExpando(searchQuery, searchContext, expandoAttributes);
160 }
161 }
162 }
163
164 protected void addContextQueryParams(
165 BooleanFilter contextFilter, SearchContext searchContext,
166 String key, Object value)
167 throws Exception {
168
169 if (key.equals("usersGroups")) {
170 if (value instanceof Long[]) {
171 Long[] values = (Long[])value;
172
173 if (ArrayUtil.isEmpty(values)) {
174 return;
175 }
176
177 TermsFilter userGroupsTermsFilter = new TermsFilter("groupIds");
178
179 userGroupsTermsFilter.addValues(
180 ArrayUtil.toStringArray(values));
181
182 contextFilter.add(
183 userGroupsTermsFilter, BooleanClauseOccur.MUST);
184 }
185 else {
186 contextFilter.addRequiredTerm(
187 "groupIds", String.valueOf(value));
188 }
189 }
190 else if (key.equals("usersOrgs")) {
191 if (value instanceof Long[]) {
192 Long[] values = (Long[])value;
193
194 if (ArrayUtil.isEmpty(values)) {
195 return;
196 }
197
198 TermsFilter organizationsTermsFilter = new TermsFilter(
199 "organizationIds");
200 TermsFilter ancestorOrgsTermsFilter = new TermsFilter(
201 "ancestorOrganizationIds");
202
203 String[] organizationIdsStrings = ArrayUtil.toStringArray(
204 values);
205
206 ancestorOrgsTermsFilter.addValues(organizationIdsStrings);
207
208 organizationsTermsFilter.addValues(organizationIdsStrings);
209
210 BooleanFilter userOrgsBooleanFilter = new BooleanFilter();
211
212 userOrgsBooleanFilter.add(ancestorOrgsTermsFilter);
213 userOrgsBooleanFilter.add(organizationsTermsFilter);
214
215 contextFilter.add(
216 userOrgsBooleanFilter, BooleanClauseOccur.MUST);
217 }
218 else {
219 contextFilter.addRequiredTerm(
220 "organizationIds", String.valueOf(value));
221 }
222 }
223 else if (key.equals("usersOrgsCount")) {
224 contextFilter.addRequiredTerm(
225 "organizationCount", String.valueOf(value));
226 }
227 else if (key.equals("usersRoles")) {
228 contextFilter.addRequiredTerm("roleIds", String.valueOf(value));
229 }
230 else if (key.equals("usersTeams")) {
231 contextFilter.addRequiredTerm("teamIds", String.valueOf(value));
232 }
233 else if (key.equals("usersUserGroups")) {
234 contextFilter.addRequiredTerm(
235 "userGroupIds", String.valueOf(value));
236 }
237 }
238
239 @Override
240 protected void doDelete(Object obj) throws Exception {
241 User user = (User)obj;
242
243 deleteDocument(user.getCompanyId(), user.getUserId());
244
245 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(Contact.class);
246
247 Contact contact = new ContactImpl();
248
249 contact.setContactId(user.getContactId());
250 contact.setCompanyId(user.getCompanyId());
251
252 indexer.delete(contact);
253 }
254
255 @Override
256 protected Document doGetDocument(Object obj) throws Exception {
257 User user = (User)obj;
258
259 Document document = getBaseModelDocument(CLASS_NAME, user);
260
261 long[] organizationIds = user.getOrganizationIds();
262
263 document.addKeyword(Field.COMPANY_ID, user.getCompanyId());
264 document.addKeyword(Field.GROUP_ID, user.getGroupIds());
265 document.addDate(Field.MODIFIED_DATE, user.getModifiedDate());
266 document.addKeyword(Field.SCOPE_GROUP_ID, user.getGroupIds());
267 document.addKeyword(Field.STATUS, user.getStatus());
268 document.addKeyword(Field.USER_ID, user.getUserId());
269 document.addKeyword(Field.USER_NAME, user.getFullName());
270
271 document.addKeyword(
272 "ancestorOrganizationIds",
273 getAncestorOrganizationIds(user.getOrganizationIds()));
274 document.addText("emailAddress", user.getEmailAddress());
275 document.addText("firstName", user.getFirstName());
276 document.addText("fullName", user.getFullName());
277 document.addKeyword("groupIds", user.getGroupIds());
278 document.addText("jobTitle", user.getJobTitle());
279 document.addText("lastName", user.getLastName());
280 document.addText("middleName", user.getMiddleName());
281 document.addKeyword("organizationIds", organizationIds);
282 document.addKeyword(
283 "organizationCount", String.valueOf(organizationIds.length));
284 document.addKeyword("roleIds", user.getRoleIds());
285 document.addText("screenName", user.getScreenName());
286 document.addKeyword("teamIds", user.getTeamIds());
287 document.addKeyword("userGroupIds", user.getUserGroupIds());
288
289 populateAddresses(document, user.getAddresses(), 0, 0);
290
291 return document;
292 }
293
294 @Override
295 protected String doGetSortField(String orderByCol) {
296 if (orderByCol.equals("email-address")) {
297 return "emailAddress";
298 }
299 else if (orderByCol.equals("first-name")) {
300 return "firstName";
301 }
302 else if (orderByCol.equals("job-title")) {
303 return "jobTitle";
304 }
305 else if (orderByCol.equals("last-name")) {
306 return "lastName";
307 }
308 else if (orderByCol.equals("screen-name")) {
309 return "screenName";
310 }
311 else {
312 return orderByCol;
313 }
314 }
315
316 @Override
317 protected Summary doGetSummary(
318 Document document, Locale locale, String snippet,
319 PortletRequest portletRequest, PortletResponse portletResponse) {
320
321 String firstName = document.get("firstName");
322 String middleName = document.get("middleName");
323 String lastName = document.get("lastName");
324
325 FullNameGenerator fullNameGenerator =
326 FullNameGeneratorFactory.getInstance();
327
328 String title = fullNameGenerator.getFullName(
329 firstName, middleName, lastName);
330
331 String content = null;
332
333 return new Summary(title, content);
334 }
335
336 @Override
337 protected void doReindex(Object obj) throws Exception {
338 if (obj instanceof Long) {
339 long userId = (Long)obj;
340
341 User user = UserLocalServiceUtil.getUserById(userId);
342
343 doReindex(user);
344 }
345 else if (obj instanceof long[]) {
346 long[] userIds = (long[])obj;
347
348 Map<Long, Collection<Document>> documentsMap = new HashMap<>();
349
350 for (long userId : userIds) {
351 User user = UserLocalServiceUtil.getUserById(userId);
352
353 if (user.isDefaultUser()) {
354 continue;
355 }
356
357 Document document = getDocument(user);
358
359 long companyId = user.getCompanyId();
360
361 Collection<Document> documents = documentsMap.get(companyId);
362
363 if (documents == null) {
364 documents = new ArrayList<>();
365
366 documentsMap.put(companyId, documents);
367 }
368
369 documents.add(document);
370 }
371
372 for (Map.Entry<Long, Collection<Document>> entry :
373 documentsMap.entrySet()) {
374
375 long companyId = entry.getKey();
376 Collection<Document> documents = entry.getValue();
377
378 SearchEngineUtil.updateDocuments(
379 getSearchEngineId(), companyId, documents,
380 isCommitImmediately());
381 }
382 }
383 else if (obj instanceof User) {
384 User user = (User)obj;
385
386 if (user.isDefaultUser()) {
387 return;
388 }
389
390 Document document = getDocument(user);
391
392 SearchEngineUtil.updateDocument(
393 getSearchEngineId(), user.getCompanyId(), document,
394 isCommitImmediately());
395
396 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
397 Contact.class);
398
399 try {
400 indexer.reindex(user.getContact());
401 }
402 catch (NoSuchContactException nsce) {
403
404
405
406 if (_log.isDebugEnabled()) {
407 _log.debug(nsce, nsce);
408 }
409 }
410 }
411 }
412
413 @Override
414 protected void doReindex(String className, long classPK) throws Exception {
415 User user = UserLocalServiceUtil.getUserById(classPK);
416
417 doReindex(user);
418 }
419
420 @Override
421 protected void doReindex(String[] ids) throws Exception {
422 long companyId = GetterUtil.getLong(ids[0]);
423
424 reindexUsers(companyId);
425 }
426
427 protected long[] getAncestorOrganizationIds(long[] organizationIds)
428 throws Exception {
429
430 Set<Long> ancestorOrganizationIds = new HashSet<>();
431
432 for (long organizationId : organizationIds) {
433 Organization organization =
434 OrganizationLocalServiceUtil.getOrganization(organizationId);
435
436 for (long ancestorOrganizationId :
437 organization.getAncestorOrganizationIds()) {
438
439 ancestorOrganizationIds.add(ancestorOrganizationId);
440 }
441 }
442
443 return ArrayUtil.toLongArray(ancestorOrganizationIds);
444 }
445
446 protected void reindexUsers(long companyId) throws PortalException {
447 final ActionableDynamicQuery actionableDynamicQuery =
448 UserLocalServiceUtil.getActionableDynamicQuery();
449
450 actionableDynamicQuery.setCompanyId(companyId);
451 actionableDynamicQuery.setPerformActionMethod(
452 new ActionableDynamicQuery.PerformActionMethod() {
453
454 @Override
455 public void performAction(Object object) {
456 User user = (User)object;
457
458 if (!user.isDefaultUser()) {
459 try {
460 Document document = getDocument(user);
461
462 actionableDynamicQuery.addDocument(document);
463 }
464 catch (PortalException pe) {
465 if (_log.isWarnEnabled()) {
466 _log.warn(
467 "Unable to index user " + user.getUserId(),
468 pe);
469 }
470 }
471 }
472 }
473
474 });
475 actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
476
477 actionableDynamicQuery.performActions();
478 }
479
480 private static final Log _log = LogFactoryUtil.getLog(UserIndexer.class);
481
482 }