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