1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.enterpriseadmin.util;
16  
17  import com.liferay.portal.kernel.search.BooleanClauseOccur;
18  import com.liferay.portal.kernel.search.BooleanQuery;
19  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
20  import com.liferay.portal.kernel.search.Document;
21  import com.liferay.portal.kernel.search.DocumentImpl;
22  import com.liferay.portal.kernel.search.Field;
23  import com.liferay.portal.kernel.search.SearchContext;
24  import com.liferay.portal.kernel.search.SearchEngineUtil;
25  import com.liferay.portal.kernel.search.Summary;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.SetUtil;
28  import com.liferay.portal.kernel.util.UnicodeProperties;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.model.Organization;
31  import com.liferay.portal.model.User;
32  import com.liferay.portal.search.BaseIndexer;
33  import com.liferay.portal.security.auth.FullNameGenerator;
34  import com.liferay.portal.security.auth.FullNameGeneratorFactory;
35  import com.liferay.portal.service.OrganizationLocalServiceUtil;
36  import com.liferay.portal.service.UserLocalServiceUtil;
37  import com.liferay.portal.util.PortletKeys;
38  import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
39  import com.liferay.portlet.expando.model.ExpandoBridge;
40  import com.liferay.portlet.expando.model.ExpandoColumnConstants;
41  import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
42  import com.liferay.portlet.expando.util.ExpandoBridgeIndexer;
43  import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
44  
45  import java.util.ArrayList;
46  import java.util.Collection;
47  import java.util.HashMap;
48  import java.util.LinkedHashMap;
49  import java.util.List;
50  import java.util.Map;
51  import java.util.Set;
52  
53  import javax.portlet.PortletURL;
54  
55  /**
56   * <a href="UserIndexer.java.html"><b><i>View Source</i></b></a>
57   *
58   * @author Raymond Augé
59   * @author Zsigmond Rab
60   */
61  public class UserIndexer extends BaseIndexer {
62  
63      public static final String[] CLASS_NAMES = {User.class.getName()};
64  
65      public static final String PORTLET_ID = PortletKeys.ENTERPRISE_ADMIN_USERS;
66  
67      public String[] getClassNames() {
68          return CLASS_NAMES;
69      }
70  
71      public Summary getSummary(
72          Document document, String snippet, PortletURL portletURL) {
73  
74          String firstName = document.get("firstName");
75          String middleName = document.get("middleName");
76          String lastName = document.get("lastName");
77  
78          FullNameGenerator fullNameGenerator =
79              FullNameGeneratorFactory.getInstance();
80  
81          String title = fullNameGenerator.getFullName(
82              firstName, middleName, lastName);
83  
84          String content = null;
85  
86          String userId = document.get(Field.USER_ID);
87  
88          portletURL.setParameter("struts_action", "/enterprise_admin/edit_user");
89          portletURL.setParameter("p_u_i_d", userId);
90  
91          return new Summary(title, content, portletURL);
92      }
93  
94      protected void addContextQueryParams(
95              BooleanQuery contextQuery, String key, Object value)
96          throws Exception {
97  
98          if (key.equals("usersOrgs")) {
99              if (value instanceof Long[]) {
100                 Long[] values = (Long[])value;
101 
102                 BooleanQuery usersOrgsQuery =
103                     BooleanQueryFactoryUtil.create();
104 
105                 for (long organizationId : values) {
106                     usersOrgsQuery.addTerm(
107                         "organizationIds", organizationId);
108                     usersOrgsQuery.addTerm(
109                         "ancestorOrganizationIds", organizationId);
110                 }
111 
112                 contextQuery.add(usersOrgsQuery, BooleanClauseOccur.MUST);
113             }
114             else {
115                 contextQuery.addRequiredTerm(
116                     "organizationIds", String.valueOf(value));
117             }
118         }
119         else if (key.equals("usersRoles")) {
120             contextQuery.addRequiredTerm("roleIds", String.valueOf(value));
121         }
122         else if (key.equals("usersTeams")) {
123             contextQuery.addRequiredTerm("teamIds", String.valueOf(value));
124         }
125         else if (key.equals("usersUserGroups")) {
126             contextQuery.addRequiredTerm("userGroupIds", String.valueOf(value));
127         }
128     }
129 
130     protected void addSearchQueryParams(
131             BooleanQuery searchQuery, ExpandoBridge expandoBridge,
132             Set<String> attributeNames, String key, Object value,
133             boolean andSearch)
134         throws Exception {
135 
136         if (attributeNames.contains(key)) {
137             UnicodeProperties properties = expandoBridge.getAttributeProperties(
138                 key);
139 
140             if (GetterUtil.getBoolean(
141                     properties.getProperty(ExpandoBridgeIndexer.INDEXABLE))) {
142 
143                 int type = expandoBridge.getAttributeType(key);
144 
145                 if ((type == ExpandoColumnConstants.STRING) &&
146                     (Validator.isNotNull((String)value))) {
147 
148                     if (andSearch) {
149                         searchQuery.addRequiredTerm(key, (String)value, true);
150                     }
151                     else {
152                         searchQuery.addTerm(key, (String)value, true);
153                     }
154                 }
155             }
156         }
157         else if (Validator.isNotNull(key) && Validator.isNotNull(value)) {
158             if (andSearch) {
159                 searchQuery.addRequiredTerm(key, String.valueOf(value));
160             }
161             else {
162                 searchQuery.addTerm(key, String.valueOf(value));
163             }
164         }
165     }
166 
167     protected void doDelete(Object obj) throws Exception {
168         User user = (User)obj;
169 
170         Document document = new DocumentImpl();
171 
172         document.addUID(PORTLET_ID, user.getUserId());
173 
174         SearchEngineUtil.deleteDocument(
175             user.getCompanyId(), document.get(Field.UID));
176     }
177 
178     protected Document doGetDocument(Object obj) throws Exception {
179         User user = (User)obj;
180 
181         long companyId = user.getCompanyId();
182         long userId = user.getUserId();
183         String screenName = user.getScreenName();
184         String emailAddress = user.getEmailAddress();
185         String firstName = user.getFirstName();
186         String middleName = user.getMiddleName();
187         String lastName = user.getLastName();
188         String jobTitle = user.getJobTitle();
189         boolean active = user.isActive();
190         long[] groupIds = user.getGroupIds();
191         long[] organizationIds = user.getOrganizationIds();
192         long[] roleIds = user.getRoleIds();
193         long[] teamIds = user.getTeamIds();
194         long[] userGroupIds = user.getUserGroupIds();
195 
196         String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
197             User.class.getName(), userId);
198 
199         ExpandoBridge expandoBridge = user.getExpandoBridge();
200 
201         Document document = new DocumentImpl();
202 
203         document.addUID(PORTLET_ID, userId);
204 
205         document.addModifiedDate();
206 
207         document.addKeyword(Field.COMPANY_ID, companyId);
208         document.addKeyword(Field.PORTLET_ID, PORTLET_ID);
209         document.addKeyword(Field.USER_ID, userId);
210 
211         document.addKeyword("screenName", screenName);
212         document.addKeyword("emailAddress", emailAddress);
213         document.addKeyword("firstName", firstName, true);
214         document.addKeyword("middleName", middleName, true);
215         document.addKeyword("lastName", lastName, true);
216         document.addKeyword("jobTitle", jobTitle);
217         document.addKeyword("active", active);
218         document.addKeyword("groupIds", groupIds);
219         document.addKeyword("organizationIds", organizationIds);
220         document.addKeyword(
221             "ancestorOrganizationIds",
222             getAncestorOrganizationIds(userId, organizationIds));
223         document.addKeyword("roleIds", roleIds);
224         document.addKeyword("teamIds", teamIds);
225         document.addKeyword("userGroupIds", userGroupIds);
226 
227         document.addKeyword(Field.ASSET_TAG_NAMES, assetTagNames);
228 
229         ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
230 
231         return document;
232     }
233 
234     protected void doReindex(Object obj) throws Exception {
235         if (obj instanceof List<?>) {
236             List<User> users = (List<User>)obj;
237 
238             for (User user : users) {
239                 doReindex(user);
240             }
241         }
242         else if (obj instanceof Long) {
243             long userId = (Long)obj;
244 
245             User user = UserLocalServiceUtil.getUserById(userId);
246 
247             doReindex(user);
248         }
249         else if (obj instanceof long[]) {
250             long[] userIds = (long[])obj;
251 
252             Map<Long, Collection<Document>> documentsMap =
253                 new HashMap<Long, Collection<Document>>();
254 
255             for (long userId : userIds) {
256                 User user = UserLocalServiceUtil.getUserById(userId);
257 
258                 if (user.isDefaultUser()) {
259                     continue;
260                 }
261 
262                 Document document = getDocument(user);
263 
264                 long companyId = user.getCompanyId();
265 
266                 Collection<Document> documents = documentsMap.get(companyId);
267 
268                 if (documents == null) {
269                     documents = new ArrayList<Document>();
270 
271                     documentsMap.put(companyId, documents);
272                 }
273 
274                 documents.add(document);
275             }
276 
277             for (Map.Entry<Long, Collection<Document>> entry :
278                     documentsMap.entrySet()) {
279 
280                 long companyId = entry.getKey();
281                 Collection<Document> documents = entry.getValue();
282 
283                 SearchEngineUtil.updateDocuments(companyId, documents);
284             }
285         }
286         else if (obj instanceof User) {
287             User user = (User)obj;
288 
289             if (user.isDefaultUser()) {
290                 return;
291             }
292 
293             Document document = getDocument(user);
294 
295             SearchEngineUtil.updateDocument(user.getCompanyId(), document);
296         }
297     }
298 
299     protected void doReindex(String className, long classPK) throws Exception {
300         User user = UserLocalServiceUtil.getUserById(classPK);
301 
302         doReindex(user);
303     }
304 
305     protected void doReindex(String[] ids) throws Exception {
306         long companyId = GetterUtil.getLong(ids[0]);
307 
308         reindexUsers(companyId);
309     }
310 
311     protected long[] getAncestorOrganizationIds(
312             long userId, long[] organizationIds)
313         throws Exception {
314 
315         List<Organization> ancestorOrganizations =
316             new ArrayList<Organization>();
317 
318         for (long organizationId : organizationIds) {
319             Organization organization =
320                 OrganizationLocalServiceUtil.getOrganization(organizationId);
321 
322             ancestorOrganizations.addAll(organization.getAncestors());
323         }
324 
325         long[] ancestorOrganizationIds = new long[ancestorOrganizations.size()];
326 
327         for (int i = 0; i < ancestorOrganizations.size(); i++) {
328             Organization ancestorOrganization = ancestorOrganizations.get(i);
329 
330             ancestorOrganizationIds[i] =
331                 ancestorOrganization.getOrganizationId();
332         }
333 
334         return ancestorOrganizationIds;
335     }
336 
337     protected String getPortletId(SearchContext searchContext) {
338         return PORTLET_ID;
339     }
340 
341     protected void postProcessContextQuery(
342             BooleanQuery contextQuery, SearchContext searchContext)
343         throws Exception {
344 
345         Boolean active = (Boolean)searchContext.getAttribute("active");
346 
347         if (active != null) {
348             contextQuery.addRequiredTerm("active", active);
349         }
350 
351         LinkedHashMap<String, Object> params =
352             (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
353 
354         if (params == null) {
355             return;
356         }
357 
358         for (Map.Entry<String, Object> entry : params.entrySet()) {
359             String key = entry.getKey();
360             Object value = entry.getValue();
361 
362             if (value == null) {
363                 continue;
364             }
365 
366             addContextQueryParams(contextQuery, key, value);
367         }
368     }
369 
370     protected void postProcessSearchQuery(
371             BooleanQuery searchQuery, SearchContext searchContext)
372         throws Exception {
373 
374         Boolean andSearch = (Boolean)searchContext.getAttribute("andSearch");
375 
376         if (andSearch == null) {
377             andSearch = Boolean.TRUE;
378         }
379 
380         String firstName = (String)searchContext.getAttribute("firstName");
381 
382         if (Validator.isNotNull(firstName)) {
383             if (andSearch) {
384                 searchQuery.addRequiredTerm("firstName", firstName, true);
385             }
386             else {
387                 searchQuery.addTerm("firstName", firstName, true);
388             }
389         }
390 
391         String middleName = (String)searchContext.getAttribute("middleName");
392 
393         if (Validator.isNotNull(middleName)) {
394             if (andSearch) {
395                 searchQuery.addRequiredTerm("middleName", middleName, true);
396             }
397             else {
398                 searchQuery.addTerm("middleName", middleName, true);
399             }
400         }
401 
402         String lastName = (String)searchContext.getAttribute("lastName");
403 
404         if (Validator.isNotNull(lastName)) {
405             if (andSearch) {
406                 searchQuery.addRequiredTerm("lastName", lastName, true);
407             }
408             else {
409                 searchQuery.addTerm("lastName", lastName, true);
410             }
411         }
412 
413         String screenName = (String)searchContext.getAttribute("screenName");
414 
415         if (Validator.isNotNull(screenName)) {
416             if (andSearch) {
417                 searchQuery.addRequiredTerm("screenName", screenName, true);
418             }
419             else {
420                 searchQuery.addTerm("screenName", screenName, true);
421             }
422         }
423 
424         String emailAddress = (String)searchContext.getAttribute(
425             "emailAddress");
426 
427         if (Validator.isNotNull(emailAddress)) {
428             if (andSearch) {
429                 searchQuery.addRequiredTerm(
430                     "emailAddress", emailAddress, true);
431             }
432             else {
433                 searchQuery.addTerm("emailAddress", emailAddress, true);
434             }
435         }
436 
437         LinkedHashMap<String, Object> params =
438             (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
439 
440         if (params != null) {
441             ExpandoBridge expandoBridge =
442                 ExpandoBridgeFactoryUtil.getExpandoBridge(
443                     searchContext.getCompanyId(), User.class.getName());
444 
445             Set<String> attributeNames = SetUtil.fromEnumeration(
446                 expandoBridge.getAttributeNames());
447 
448             for (Map.Entry<String, Object> entry : params.entrySet()) {
449                 String key = entry.getKey();
450                 Object value = entry.getValue();
451 
452                 if (key.equals("usersOrgs") || key.equals("usersRoles") ||
453                     key.equals("usersTeams") || key.equals("usersUserGroups") ||
454                     (value == null)) {
455 
456                     continue;
457                 }
458 
459                 addSearchQueryParams(
460                     searchQuery, expandoBridge, attributeNames, key, value,
461                     andSearch);
462             }
463         }
464     }
465 
466     protected void reindexUsers(long companyId) throws Exception {
467         int count = UserLocalServiceUtil.getCompanyUsersCount(companyId);
468 
469         int pages = count / UserIndexer.DEFAULT_INTERVAL;
470 
471         for (int i = 0; i <= pages; i++) {
472             int start = (i * UserIndexer.DEFAULT_INTERVAL);
473             int end = start + UserIndexer.DEFAULT_INTERVAL;
474 
475             reindexUsers(companyId, start, end);
476         }
477     }
478 
479     protected void reindexUsers(long companyId, int start, int end)
480         throws Exception {
481 
482         List<User> users = UserLocalServiceUtil.getCompanyUsers(
483             companyId, start, end);
484 
485         if (users.isEmpty()) {
486             return;
487         }
488 
489         Collection<Document> documents = new ArrayList<Document>();
490 
491         for (User user : users) {
492             if (user.isDefaultUser()) {
493                 continue;
494             }
495 
496             Document document = getDocument(user);
497 
498             documents.add(document);
499         }
500 
501         SearchEngineUtil.updateDocuments(companyId, documents);
502     }
503 
504 }