001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.blogs.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.BooleanQuery;
026    import com.liferay.portal.kernel.search.Document;
027    import com.liferay.portal.kernel.search.Field;
028    import com.liferay.portal.kernel.search.SearchContext;
029    import com.liferay.portal.kernel.search.SearchEngineUtil;
030    import com.liferay.portal.kernel.search.Summary;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.HtmlUtil;
033    import com.liferay.portal.kernel.workflow.WorkflowConstants;
034    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
035    import com.liferay.portal.security.permission.ActionKeys;
036    import com.liferay.portal.security.permission.PermissionChecker;
037    import com.liferay.portal.util.PortletKeys;
038    import com.liferay.portlet.blogs.model.BlogsEntry;
039    import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
040    import com.liferay.portlet.blogs.service.permission.BlogsEntryPermission;
041    
042    import java.util.ArrayList;
043    import java.util.Collection;
044    import java.util.Date;
045    import java.util.List;
046    import java.util.Locale;
047    
048    import javax.portlet.PortletURL;
049    
050    /**
051     * @author Brian Wing Shun Chan
052     * @author Harry Mark
053     * @author Bruno Farache
054     * @author Raymond Augé
055     */
056    public class BlogsIndexer extends BaseIndexer {
057    
058            public static final String[] CLASS_NAMES = {BlogsEntry.class.getName()};
059    
060            public static final String PORTLET_ID = PortletKeys.BLOGS;
061    
062            public BlogsIndexer() {
063                    setPermissionAware(true);
064            }
065    
066            public String[] getClassNames() {
067                    return CLASS_NAMES;
068            }
069    
070            public String getPortletId() {
071                    return PORTLET_ID;
072            }
073    
074            @Override
075            public boolean hasPermission(
076                            PermissionChecker permissionChecker, String entryClassName,
077                            long entryClassPK, String actionId)
078                    throws Exception {
079    
080                    return BlogsEntryPermission.contains(
081                            permissionChecker, entryClassPK, ActionKeys.VIEW);
082            }
083    
084            @Override
085            public void postProcessContextQuery(
086                            BooleanQuery contextQuery, SearchContext searchContext)
087                    throws Exception {
088    
089                    int status = GetterUtil.getInteger(
090                            searchContext.getAttribute(Field.STATUS),
091                            WorkflowConstants.STATUS_APPROVED);
092    
093                    if (status != WorkflowConstants.STATUS_ANY) {
094                            contextQuery.addRequiredTerm(Field.STATUS, status);
095                    }
096            }
097    
098            protected void addReindexCriteria(
099                    DynamicQuery dynamicQuery, long companyId) {
100    
101                    Property companyIdProperty = PropertyFactoryUtil.forName("companyId");
102    
103                    dynamicQuery.add(companyIdProperty.eq(companyId));
104    
105                    Property displayDateProperty = PropertyFactoryUtil.forName(
106                            "displayDate");
107    
108                    dynamicQuery.add(displayDateProperty.lt(new Date()));
109    
110                    Property statusProperty = PropertyFactoryUtil.forName("status");
111    
112                    Integer[] statuses = {
113                            WorkflowConstants.STATUS_APPROVED, WorkflowConstants.STATUS_IN_TRASH
114                    };
115    
116                    dynamicQuery.add(statusProperty.in(statuses));
117            }
118    
119            @Override
120            protected void doDelete(Object obj) throws Exception {
121                    BlogsEntry entry = (BlogsEntry)obj;
122    
123                    deleteDocument(entry.getCompanyId(), entry.getEntryId());
124            }
125    
126            @Override
127            protected Document doGetDocument(Object obj) throws Exception {
128                    BlogsEntry entry = (BlogsEntry)obj;
129    
130                    Document document = getBaseModelDocument(PORTLET_ID, entry);
131    
132                    document.addText(
133                            Field.CONTENT, HtmlUtil.extractText(entry.getContent()));
134                    document.addText(Field.DESCRIPTION, entry.getDescription());
135                    document.addDate(Field.MODIFIED_DATE, entry.getDisplayDate());
136                    document.addText(Field.TITLE, entry.getTitle());
137    
138                    return document;
139            }
140    
141            @Override
142            protected Summary doGetSummary(
143                    Document document, Locale locale, String snippet,
144                    PortletURL portletURL) {
145    
146                    String entryId = document.get(Field.ENTRY_CLASS_PK);
147    
148                    portletURL.setParameter("struts_action", "/blogs/view_entry");
149                    portletURL.setParameter("entryId", entryId);
150    
151                    Summary summary = createSummary(document);
152    
153                    summary.setMaxContentLength(200);
154                    summary.setPortletURL(portletURL);
155    
156                    return summary;
157            }
158    
159            @Override
160            protected void doReindex(Object obj) throws Exception {
161                    BlogsEntry entry = (BlogsEntry)obj;
162    
163                    if (!entry.isApproved() && !entry.isInTrash()) {
164                            return;
165                    }
166    
167                    Document document = getDocument(entry);
168    
169                    SearchEngineUtil.updateDocument(
170                            getSearchEngineId(), entry.getCompanyId(), document);
171            }
172    
173            @Override
174            protected void doReindex(String className, long classPK) throws Exception {
175                    BlogsEntry entry = BlogsEntryLocalServiceUtil.getEntry(classPK);
176    
177                    doReindex(entry);
178            }
179    
180            @Override
181            protected void doReindex(String[] ids) throws Exception {
182                    long companyId = GetterUtil.getLong(ids[0]);
183    
184                    reindexEntries(companyId);
185            }
186    
187            @Override
188            protected String getPortletId(SearchContext searchContext) {
189                    return PORTLET_ID;
190            }
191    
192            protected void reindexEntries(long companyId) throws Exception {
193                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
194                            BlogsEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
195    
196                    Projection minEntryIdProjection = ProjectionFactoryUtil.min("entryId");
197                    Projection maxEntryIdProjection = ProjectionFactoryUtil.max("entryId");
198    
199                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
200    
201                    projectionList.add(minEntryIdProjection);
202                    projectionList.add(maxEntryIdProjection);
203    
204                    dynamicQuery.setProjection(projectionList);
205    
206                    addReindexCriteria(dynamicQuery, companyId);
207    
208                    List<Object[]> results = BlogsEntryLocalServiceUtil.dynamicQuery(
209                            dynamicQuery);
210    
211                    Object[] minAndMaxEntryIds = results.get(0);
212    
213                    if ((minAndMaxEntryIds[0] == null) || (minAndMaxEntryIds[1] == null)) {
214                            return;
215                    }
216    
217                    long minEntryId = (Long)minAndMaxEntryIds[0];
218                    long maxEntryId = (Long)minAndMaxEntryIds[1];
219    
220                    long startEntryId = minEntryId;
221                    long endEntryId = startEntryId + DEFAULT_INTERVAL;
222    
223                    while (startEntryId <= maxEntryId) {
224                            reindexEntries(companyId, startEntryId, endEntryId);
225    
226                            startEntryId = endEntryId;
227                            endEntryId += DEFAULT_INTERVAL;
228                    }
229            }
230    
231            protected void reindexEntries(
232                            long companyId, long startEntryId, long endEntryId)
233                    throws Exception {
234    
235                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
236                            BlogsEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
237    
238                    Property property = PropertyFactoryUtil.forName("entryId");
239    
240                    dynamicQuery.add(property.ge(startEntryId));
241                    dynamicQuery.add(property.lt(endEntryId));
242    
243                    addReindexCriteria(dynamicQuery, companyId);
244    
245                    List<BlogsEntry> entries = BlogsEntryLocalServiceUtil.dynamicQuery(
246                            dynamicQuery);
247    
248                    if (entries.isEmpty()) {
249                            return;
250                    }
251    
252                    Collection<Document> documents = new ArrayList<Document>(
253                            entries.size());
254    
255                    for (BlogsEntry entry : entries) {
256                            Document document = getDocument(entry);
257    
258                            documents.add(document);
259                    }
260    
261                    SearchEngineUtil.updateDocuments(
262                            getSearchEngineId(), companyId, documents);
263            }
264    
265    }