001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.bookmarks.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.model.Group;
035    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
036    import com.liferay.portal.service.GroupLocalServiceUtil;
037    import com.liferay.portal.util.PortletKeys;
038    import com.liferay.portlet.bookmarks.model.BookmarksEntry;
039    import com.liferay.portlet.bookmarks.model.BookmarksFolder;
040    import com.liferay.portlet.bookmarks.model.BookmarksFolderConstants;
041    import com.liferay.portlet.bookmarks.service.BookmarksEntryLocalServiceUtil;
042    import com.liferay.portlet.bookmarks.service.BookmarksFolderLocalServiceUtil;
043    import com.liferay.portlet.bookmarks.service.BookmarksFolderServiceUtil;
044    
045    import java.util.ArrayList;
046    import java.util.Collection;
047    import java.util.List;
048    import java.util.Locale;
049    
050    import javax.portlet.PortletURL;
051    
052    /**
053     * @author Brian Wing Shun Chan
054     * @author Bruno Farache
055     * @author Raymond Augé
056     */
057    public class BookmarksIndexer extends BaseIndexer {
058    
059            public static final String[] CLASS_NAMES = {BookmarksEntry.class.getName()};
060    
061            public static final String PORTLET_ID = PortletKeys.BOOKMARKS;
062    
063            public String[] getClassNames() {
064                    return CLASS_NAMES;
065            }
066    
067            public String getPortletId() {
068                    return PORTLET_ID;
069            }
070    
071            @Override
072            public boolean isPermissionAware() {
073                    return _PERMISSION_AWARE;
074            }
075    
076            @Override
077            public void postProcessContextQuery(
078                            BooleanQuery contextQuery, SearchContext searchContext)
079                    throws Exception {
080    
081                    long[] folderIds = searchContext.getFolderIds();
082    
083                    if ((folderIds != null) && (folderIds.length > 0)) {
084                            if (folderIds[0] ==
085                                            BookmarksFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
086    
087                                    return;
088                            }
089    
090                            BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create(
091                                    searchContext);
092    
093                            for (long folderId : folderIds) {
094                                    try {
095                                            BookmarksFolderServiceUtil.getFolder(folderId);
096                                    }
097                                    catch (Exception e) {
098                                            continue;
099                                    }
100    
101                                    folderIdsQuery.addTerm(Field.FOLDER_ID, folderId);
102                            }
103    
104                            contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
105                    }
106            }
107    
108            protected void addReindexCriteria(
109                    DynamicQuery dynamicQuery, long companyId) {
110    
111                    Property property = PropertyFactoryUtil.forName("companyId");
112    
113                    dynamicQuery.add(property.eq(companyId));
114            }
115    
116            protected void addReindexCriteria(
117                    DynamicQuery dynamicQuery, long groupId, long folderId) {
118    
119                    Property groupIdProperty = PropertyFactoryUtil.forName("groupId");
120    
121                    dynamicQuery.add(groupIdProperty.eq(groupId));
122    
123                    Property folderIdProperty = PropertyFactoryUtil.forName("folderId");
124    
125                    dynamicQuery.add(folderIdProperty.eq(folderId));
126            }
127    
128            @Override
129            protected void doDelete(Object obj) throws Exception {
130                    BookmarksEntry entry = (BookmarksEntry)obj;
131    
132                    deleteDocument(entry.getCompanyId(), entry.getEntryId());
133            }
134    
135            @Override
136            protected Document doGetDocument(Object obj) throws Exception {
137                    BookmarksEntry entry = (BookmarksEntry)obj;
138    
139                    Document document = getBaseModelDocument(PORTLET_ID, entry);
140    
141                    document.addText(Field.DESCRIPTION, entry.getDescription());
142                    document.addKeyword(Field.FOLDER_ID, entry.getFolderId());
143                    document.addText(Field.TITLE, entry.getName());
144                    document.addText(Field.URL, entry.getUrl());
145    
146                    return document;
147            }
148    
149            @Override
150            protected Summary doGetSummary(
151                    Document document, Locale locale, String snippet,
152                    PortletURL portletURL) {
153    
154                    String title = document.get(Field.TITLE);
155    
156                    String url = document.get(Field.URL);
157    
158                    String entryId = document.get(Field.ENTRY_CLASS_PK);
159    
160                    portletURL.setParameter("struts_action", "/bookmarks/view_entry");
161                    portletURL.setParameter("entryId", entryId);
162    
163                    return new Summary(title, url, portletURL);
164            }
165    
166            @Override
167            protected void doReindex(Object obj) throws Exception {
168                    BookmarksEntry entry = (BookmarksEntry)obj;
169    
170                    Document document = getDocument(entry);
171    
172                    SearchEngineUtil.updateDocument(
173                            getSearchEngineId(), entry.getCompanyId(), document);
174            }
175    
176            @Override
177            protected void doReindex(String className, long classPK) throws Exception {
178                    BookmarksEntry entry = BookmarksEntryLocalServiceUtil.getEntry(classPK);
179    
180                    doReindex(entry);
181            }
182    
183            @Override
184            protected void doReindex(String[] ids) throws Exception {
185                    long companyId = GetterUtil.getLong(ids[0]);
186    
187                    reindexFolders(companyId);
188                    reindexRoot(companyId);
189            }
190    
191            @Override
192            protected String getPortletId(SearchContext searchContext) {
193                    return PORTLET_ID;
194            }
195    
196            protected void reindexEntries(long companyId, long groupId, long folderId)
197                    throws Exception {
198    
199                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
200                            BookmarksEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
201    
202                    Projection minEntryIdProjection = ProjectionFactoryUtil.min("entryId");
203                    Projection maxEntryIdProjection = ProjectionFactoryUtil.max("entryId");
204    
205                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
206    
207                    projectionList.add(minEntryIdProjection);
208                    projectionList.add(maxEntryIdProjection);
209    
210                    dynamicQuery.setProjection(projectionList);
211    
212                    addReindexCriteria(dynamicQuery, groupId, folderId);
213    
214                    List<Object[]> results = BookmarksEntryLocalServiceUtil.dynamicQuery(
215                            dynamicQuery);
216    
217                    Object[] minAndMaxEntryIds = results.get(0);
218    
219                    if ((minAndMaxEntryIds[0] == null) || (minAndMaxEntryIds[1] == null)) {
220                            return;
221                    }
222    
223                    long minEntryId = (Long)minAndMaxEntryIds[0];
224                    long maxEntryId = (Long)minAndMaxEntryIds[1];
225    
226                    long startEntryId = minEntryId;
227                    long endEntryId = startEntryId + DEFAULT_INTERVAL;
228    
229                    while (startEntryId <= maxEntryId) {
230                            reindexEntries(
231                                    companyId, groupId, folderId, startEntryId, endEntryId);
232    
233                            startEntryId = endEntryId;
234                            endEntryId += DEFAULT_INTERVAL;
235                    }
236            }
237    
238            protected void reindexEntries(
239                            long companyId, long groupId, long folderId, long startEntryId,
240                            long endEntryId)
241                    throws Exception {
242    
243                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
244                            BookmarksEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
245    
246                    Property property = PropertyFactoryUtil.forName("entryId");
247    
248                    dynamicQuery.add(property.ge(startEntryId));
249                    dynamicQuery.add(property.lt(endEntryId));
250    
251                    addReindexCriteria(dynamicQuery, groupId, folderId);
252    
253                    List<BookmarksEntry> entries =
254                            BookmarksEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
255    
256                    if (entries.isEmpty()) {
257                            return;
258                    }
259    
260                    Collection<Document> documents = new ArrayList<Document>(
261                            entries.size());
262    
263                    for (BookmarksEntry entry : entries) {
264                            Document document = getDocument(entry);
265    
266                            documents.add(document);
267                    }
268    
269                    SearchEngineUtil.updateDocuments(
270                            getSearchEngineId(), companyId, documents);
271            }
272    
273            protected void reindexFolders(long companyId) throws Exception {
274                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
275                            BookmarksFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
276    
277                    Projection minFolderIdProjection = ProjectionFactoryUtil.min(
278                            "folderId");
279                    Projection maxFolderIdProjection = ProjectionFactoryUtil.max(
280                            "folderId");
281    
282                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
283    
284                    projectionList.add(minFolderIdProjection);
285                    projectionList.add(maxFolderIdProjection);
286    
287                    dynamicQuery.setProjection(projectionList);
288    
289                    addReindexCriteria(dynamicQuery, companyId);
290    
291                    List<Object[]> results = BookmarksFolderLocalServiceUtil.dynamicQuery(
292                            dynamicQuery);
293    
294                    Object[] minAndMaxFolderIds = results.get(0);
295    
296                    if ((minAndMaxFolderIds[0] == null) ||
297                            (minAndMaxFolderIds[1] == null)) {
298    
299                            return;
300                    }
301    
302                    long minFolderId = (Long)minAndMaxFolderIds[0];
303                    long maxFolderId = (Long)minAndMaxFolderIds[1];
304    
305                    long startFolderId = minFolderId;
306                    long endFolderId = startFolderId + DEFAULT_INTERVAL;
307    
308                    while (startFolderId <= maxFolderId) {
309                            reindexFolders(companyId, startFolderId, endFolderId);
310    
311                            startFolderId = endFolderId;
312                            endFolderId += DEFAULT_INTERVAL;
313                    }
314            }
315    
316            protected void reindexFolders(
317                            long companyId, long startFolderId, long endFolderId)
318                    throws Exception {
319    
320                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
321                            BookmarksFolder.class, PACLClassLoaderUtil.getPortalClassLoader());
322    
323                    Property property = PropertyFactoryUtil.forName("folderId");
324    
325                    dynamicQuery.add(property.ge(startFolderId));
326                    dynamicQuery.add(property.lt(endFolderId));
327    
328                    addReindexCriteria(dynamicQuery, companyId);
329    
330                    List<BookmarksFolder> folders =
331                            BookmarksFolderLocalServiceUtil.dynamicQuery(dynamicQuery);
332    
333                    for (BookmarksFolder folder : folders) {
334                            long groupId = folder.getGroupId();
335                            long folderId = folder.getFolderId();
336    
337                            reindexEntries(companyId, groupId, folderId);
338                    }
339            }
340    
341            protected void reindexRoot(long companyId) throws Exception {
342                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
343                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
344    
345                    Projection minGroupIdProjection = ProjectionFactoryUtil.min("groupId");
346                    Projection maxGroupIdProjection = ProjectionFactoryUtil.max("groupId");
347    
348                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
349    
350                    projectionList.add(minGroupIdProjection);
351                    projectionList.add(maxGroupIdProjection);
352    
353                    dynamicQuery.setProjection(projectionList);
354    
355                    addReindexCriteria(dynamicQuery, companyId);
356    
357                    List<Object[]> results = GroupLocalServiceUtil.dynamicQuery(
358                            dynamicQuery);
359    
360                    Object[] minAndMaxGroupIds = results.get(0);
361    
362                    if ((minAndMaxGroupIds[0] == null) || (minAndMaxGroupIds[1] == null)) {
363                            return;
364                    }
365    
366                    long minGroupId = (Long)minAndMaxGroupIds[0];
367                    long maxGroupId = (Long)minAndMaxGroupIds[1];
368    
369                    long startGroupId = minGroupId;
370                    long endGroupId = startGroupId + DEFAULT_INTERVAL;
371    
372                    while (startGroupId <= maxGroupId) {
373                            reindexRoot(companyId, startGroupId, endGroupId);
374    
375                            startGroupId = endGroupId;
376                            endGroupId += DEFAULT_INTERVAL;
377                    }
378            }
379    
380            protected void reindexRoot(
381                            long companyId, long startGroupId, long endGroupId)
382                    throws Exception {
383    
384                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
385                            Group.class, PACLClassLoaderUtil.getPortalClassLoader());
386    
387                    Property property = PropertyFactoryUtil.forName("groupId");
388    
389                    dynamicQuery.add(property.ge(startGroupId));
390                    dynamicQuery.add(property.lt(endGroupId));
391    
392                    addReindexCriteria(dynamicQuery, companyId);
393    
394                    List<Group> groups = GroupLocalServiceUtil.dynamicQuery(dynamicQuery);
395    
396                    for (Group group : groups) {
397                            long groupId = group.getGroupId();
398                            long folderId = BookmarksFolderConstants.DEFAULT_PARENT_FOLDER_ID;
399    
400                            reindexEntries(companyId, groupId, folderId);
401                    }
402            }
403    
404            private static final boolean _PERMISSION_AWARE = true;
405    
406    }