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