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