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.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.util.StringUtil;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.workflow.WorkflowConstants;
036    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
037    import com.liferay.portal.security.permission.ActionKeys;
038    import com.liferay.portal.security.permission.PermissionChecker;
039    import com.liferay.portal.util.PortletKeys;
040    import com.liferay.portlet.blogs.model.BlogsEntry;
041    import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
042    import com.liferay.portlet.blogs.service.permission.BlogsEntryPermission;
043    
044    import java.util.ArrayList;
045    import java.util.Collection;
046    import java.util.Date;
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 Harry Mark
055     * @author Bruno Farache
056     * @author Raymond Augé
057     */
058    public class BlogsIndexer extends BaseIndexer {
059    
060            public static final String[] CLASS_NAMES = {BlogsEntry.class.getName()};
061    
062            public static final String PORTLET_ID = PortletKeys.BLOGS;
063    
064            public String[] getClassNames() {
065                    return CLASS_NAMES;
066            }
067    
068            public String getPortletId() {
069                    return PORTLET_ID;
070            }
071    
072            @Override
073            public boolean hasPermission(
074                            PermissionChecker permissionChecker, long entryClassPK,
075                            String actionId)
076                    throws Exception {
077    
078                    return BlogsEntryPermission.contains(
079                            permissionChecker, entryClassPK, ActionKeys.VIEW);
080            }
081    
082            @Override
083            public boolean isFilterSearch() {
084                    return _FILTER_SEARCH;
085            }
086    
087            @Override
088            public boolean isPermissionAware() {
089                    return _PERMISSION_AWARE;
090            }
091    
092            @Override
093            public void postProcessContextQuery(
094                            BooleanQuery contextQuery, SearchContext searchContext)
095                    throws Exception {
096    
097                    int status = GetterUtil.getInteger(
098                            searchContext.getAttribute(Field.STATUS),
099                            WorkflowConstants.STATUS_ANY);
100    
101                    if (status != WorkflowConstants.STATUS_ANY) {
102                            contextQuery.addRequiredTerm(Field.STATUS, status);
103                    }
104            }
105    
106            protected void addReindexCriteria(
107                    DynamicQuery dynamicQuery, long companyId) {
108    
109                    Property companyIdProperty = PropertyFactoryUtil.forName("companyId");
110    
111                    dynamicQuery.add(companyIdProperty.eq(companyId));
112    
113                    Property displayDateProperty = PropertyFactoryUtil.forName(
114                            "displayDate");
115    
116                    dynamicQuery.add(displayDateProperty.lt(new Date()));
117    
118                    Property statusProperty = PropertyFactoryUtil.forName("status");
119    
120                    dynamicQuery.add(statusProperty.eq(WorkflowConstants.STATUS_APPROVED));
121            }
122    
123            @Override
124            protected void doDelete(Object obj) throws Exception {
125                    BlogsEntry entry = (BlogsEntry)obj;
126    
127                    deleteDocument(entry.getCompanyId(), entry.getEntryId());
128            }
129    
130            @Override
131            protected Document doGetDocument(Object obj) throws Exception {
132                    BlogsEntry entry = (BlogsEntry)obj;
133    
134                    Document document = getBaseModelDocument(PORTLET_ID, entry);
135    
136                    document.addText(
137                            Field.CONTENT, HtmlUtil.extractText(entry.getContent()));
138                    document.addDate(Field.MODIFIED_DATE, entry.getDisplayDate());
139                    document.addText(Field.TITLE, entry.getTitle());
140    
141                    return document;
142            }
143    
144            @Override
145            protected Summary doGetSummary(
146                    Document document, Locale locale, String snippet,
147                    PortletURL portletURL) {
148    
149                    String title = document.get(Field.TITLE);
150    
151                    String content = snippet;
152    
153                    if (Validator.isNull(snippet)) {
154                            content = StringUtil.shorten(document.get(Field.CONTENT), 200);
155                    }
156    
157                    String entryId = document.get(Field.ENTRY_CLASS_PK);
158    
159                    portletURL.setParameter("struts_action", "/blogs/view_entry");
160                    portletURL.setParameter("entryId", entryId);
161    
162                    return new Summary(title, content, portletURL);
163            }
164    
165            @Override
166            protected void doReindex(Object obj) throws Exception {
167                    BlogsEntry entry = (BlogsEntry)obj;
168    
169                    if (!entry.isApproved()) {
170                            return;
171                    }
172    
173                    Document document = getDocument(entry);
174    
175                    SearchEngineUtil.updateDocument(
176                            getSearchEngineId(), entry.getCompanyId(), document);
177            }
178    
179            @Override
180            protected void doReindex(String className, long classPK) throws Exception {
181                    BlogsEntry entry = BlogsEntryLocalServiceUtil.getEntry(classPK);
182    
183                    doReindex(entry);
184            }
185    
186            @Override
187            protected void doReindex(String[] ids) throws Exception {
188                    long companyId = GetterUtil.getLong(ids[0]);
189    
190                    reindexEntries(companyId);
191            }
192    
193            @Override
194            protected String getPortletId(SearchContext searchContext) {
195                    return PORTLET_ID;
196            }
197    
198            protected void reindexEntries(long companyId) throws Exception {
199                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
200                            BlogsEntry.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, companyId);
213    
214                    List<Object[]> results = BlogsEntryLocalServiceUtil.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(companyId, startEntryId, endEntryId);
231    
232                            startEntryId = endEntryId;
233                            endEntryId += DEFAULT_INTERVAL;
234                    }
235            }
236    
237            protected void reindexEntries(
238                            long companyId, long startEntryId, long endEntryId)
239                    throws Exception {
240    
241                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
242                            BlogsEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
243    
244                    Property property = PropertyFactoryUtil.forName("entryId");
245    
246                    dynamicQuery.add(property.ge(startEntryId));
247                    dynamicQuery.add(property.lt(endEntryId));
248    
249                    addReindexCriteria(dynamicQuery, companyId);
250    
251                    List<BlogsEntry> entries = BlogsEntryLocalServiceUtil.dynamicQuery(
252                            dynamicQuery);
253    
254                    if (entries.isEmpty()) {
255                            return;
256                    }
257    
258                    Collection<Document> documents = new ArrayList<Document>(
259                            entries.size());
260    
261                    for (BlogsEntry entry : entries) {
262                            Document document = getDocument(entry);
263    
264                            documents.add(document);
265                    }
266    
267                    SearchEngineUtil.updateDocuments(
268                            getSearchEngineId(), companyId, documents);
269            }
270    
271            private static final boolean _FILTER_SEARCH = true;
272    
273            private static final boolean _PERMISSION_AWARE = true;
274    
275    }