001    /**
002     * Copyright (c) 2000-2013 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.wiki.util;
016    
017    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.Property;
020    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.repository.model.FileEntry;
026    import com.liferay.portal.kernel.search.BaseIndexer;
027    import com.liferay.portal.kernel.search.BooleanClauseOccur;
028    import com.liferay.portal.kernel.search.BooleanQuery;
029    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
030    import com.liferay.portal.kernel.search.Document;
031    import com.liferay.portal.kernel.search.DocumentImpl;
032    import com.liferay.portal.kernel.search.Field;
033    import com.liferay.portal.kernel.search.Indexer;
034    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
035    import com.liferay.portal.kernel.search.SearchContext;
036    import com.liferay.portal.kernel.search.SearchEngineUtil;
037    import com.liferay.portal.kernel.search.Summary;
038    import com.liferay.portal.kernel.util.ArrayUtil;
039    import com.liferay.portal.kernel.util.GetterUtil;
040    import com.liferay.portal.kernel.util.HtmlUtil;
041    import com.liferay.portal.kernel.util.Validator;
042    import com.liferay.portal.security.permission.ActionKeys;
043    import com.liferay.portal.security.permission.PermissionChecker;
044    import com.liferay.portal.util.PortalUtil;
045    import com.liferay.portal.util.PortletKeys;
046    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
047    import com.liferay.portlet.messageboards.model.MBMessage;
048    import com.liferay.portlet.trash.util.TrashUtil;
049    import com.liferay.portlet.wiki.model.WikiNode;
050    import com.liferay.portlet.wiki.model.WikiPage;
051    import com.liferay.portlet.wiki.service.WikiNodeServiceUtil;
052    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
053    import com.liferay.portlet.wiki.service.permission.WikiPagePermission;
054    import com.liferay.portlet.wiki.service.persistence.WikiNodeActionableDynamicQuery;
055    import com.liferay.portlet.wiki.service.persistence.WikiPageActionableDynamicQuery;
056    
057    import java.util.Locale;
058    
059    import javax.portlet.PortletURL;
060    
061    /**
062     * @author Brian Wing Shun Chan
063     * @author Harry Mark
064     * @author Bruno Farache
065     * @author Raymond Aug??
066     */
067    public class WikiPageIndexer extends BaseIndexer {
068    
069            public static final String[] CLASS_NAMES = {WikiPage.class.getName()};
070    
071            public static final String PORTLET_ID = PortletKeys.WIKI;
072    
073            public WikiPageIndexer() {
074                    setFilterSearch(true);
075                    setPermissionAware(true);
076            }
077    
078            @Override
079            public void addRelatedEntryFields(Document document, Object obj)
080                    throws Exception {
081    
082                    WikiPage page = null;
083    
084                    try {
085                            if (obj instanceof DLFileEntry) {
086                                    DLFileEntry dlFileEntry = (DLFileEntry)obj;
087    
088                                    page = WikiPageAttachmentsUtil.getPage(
089                                            dlFileEntry.getFileEntryId());
090    
091                                    document.addKeyword(
092                                            Field.CLASS_NAME_ID,
093                                            PortalUtil.getClassNameId(WikiPage.class.getName()));
094                                    document.addKeyword(Field.CLASS_PK, page.getResourcePrimKey());
095                            }
096                            else if (obj instanceof MBMessage) {
097                                    MBMessage message = (MBMessage)obj;
098    
099                                    page = WikiPageLocalServiceUtil.getPage(message.getClassPK());
100                            }
101                    }
102                    catch (Exception e) {
103                            return;
104                    }
105    
106                    document.addKeyword(Field.NODE_ID, page.getNodeId());
107                    document.addKeyword(Field.RELATED_ENTRY, true);
108            }
109    
110            @Override
111            public String[] getClassNames() {
112                    return CLASS_NAMES;
113            }
114    
115            @Override
116            public String getPortletId() {
117                    return PORTLET_ID;
118            }
119    
120            @Override
121            public boolean hasPermission(
122                            PermissionChecker permissionChecker, String entryClassName,
123                            long entryClassPK, String actionId)
124                    throws Exception {
125    
126                    WikiPage page = WikiPageLocalServiceUtil.getPage(entryClassPK);
127    
128                    return WikiPagePermission.contains(
129                            permissionChecker, page, ActionKeys.VIEW);
130            }
131    
132            @Override
133            public boolean isVisible(long classPK, int status) throws Exception {
134                    WikiPage page = WikiPageLocalServiceUtil.getPage(classPK);
135    
136                    return isVisible(page.getStatus(), status);
137            }
138    
139            @Override
140            public void postProcessContextQuery(
141                            BooleanQuery contextQuery, SearchContext searchContext)
142                    throws Exception {
143    
144                    addStatus(contextQuery, searchContext);
145    
146                    long[] nodeIds = searchContext.getNodeIds();
147    
148                    if (ArrayUtil.isNotEmpty(nodeIds)) {
149                            BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create(
150                                    searchContext);
151    
152                            for (long nodeId : nodeIds) {
153                                    try {
154                                            WikiNodeServiceUtil.getNode(nodeId);
155                                    }
156                                    catch (Exception e) {
157                                            if (_log.isDebugEnabled()) {
158                                                    _log.debug("Unable to get wiki node " + nodeId, e);
159                                            }
160    
161                                            continue;
162                                    }
163    
164                                    nodeIdsQuery.addTerm(Field.NODE_ID, nodeId);
165                            }
166    
167                            contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
168                    }
169            }
170    
171            @Override
172            protected void doDelete(Object obj) throws Exception {
173                    SearchContext searchContext = new SearchContext();
174    
175                    searchContext.setSearchEngineId(getSearchEngineId());
176    
177                    if (obj instanceof Object[]) {
178                            Object[] array = (Object[])obj;
179    
180                            long companyId = (Long)array[0];
181                            long nodeId = (Long)array[1];
182                            String title = (String)array[2];
183    
184                            Document document = new DocumentImpl();
185    
186                            document.addUID(PORTLET_ID, nodeId, title);
187    
188                            SearchEngineUtil.deleteDocument(
189                                    getSearchEngineId(), companyId, document.get(Field.UID));
190                    }
191                    else if (obj instanceof WikiPage) {
192                            WikiPage page = (WikiPage)obj;
193    
194                            deleteDocument(page.getCompanyId(), page.getResourcePrimKey());
195                    }
196            }
197    
198            @Override
199            protected Document doGetDocument(Object obj) throws Exception {
200                    WikiPage page = (WikiPage)obj;
201    
202                    Document document = getBaseModelDocument(PORTLET_ID, page);
203    
204                    String content = HtmlUtil.extractText(
205                            WikiUtil.convert(page, null, null, null));
206    
207                    document.addText(Field.CONTENT, content);
208    
209                    document.addKeyword(Field.NODE_ID, page.getNodeId());
210    
211                    String title = page.getTitle();
212    
213                    if (page.isInTrash()) {
214                            title = TrashUtil.getOriginalTitle(title);
215                    }
216    
217                    document.addText(Field.TITLE, title);
218    
219                    return document;
220            }
221    
222            @Override
223            protected Summary doGetSummary(
224                    Document document, Locale locale, String snippet,
225                    PortletURL portletURL) {
226    
227                    Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
228    
229                    summary.setMaxContentLength(200);
230    
231                    String nodeId = document.get("nodeId");
232    
233                    portletURL.setParameter("struts_action", "/wiki/view");
234                    portletURL.setParameter("nodeId", nodeId);
235                    portletURL.setParameter("title", summary.getTitle());
236    
237                    summary.setPortletURL(portletURL);
238    
239                    return summary;
240            }
241    
242            @Override
243            protected void doReindex(Object obj) throws Exception {
244                    WikiPage page = (WikiPage)obj;
245    
246                    if (!page.isHead() || (!page.isApproved() && !page.isInTrash())) {
247                            return;
248                    }
249    
250                    if (Validator.isNotNull(page.getRedirectTitle())) {
251                            return;
252                    }
253    
254                    Document document = getDocument(page);
255    
256                    SearchEngineUtil.updateDocument(
257                            getSearchEngineId(), page.getCompanyId(), document);
258    
259                    reindexAttachments(page);
260            }
261    
262            @Override
263            protected void doReindex(String className, long classPK) throws Exception {
264                    WikiPage page = WikiPageLocalServiceUtil.fetchWikiPage(classPK);
265    
266                    if (page == null) {
267                            page = WikiPageLocalServiceUtil.getPage(classPK, (Boolean)null);
268                    }
269    
270                    doReindex(page);
271            }
272    
273            @Override
274            protected void doReindex(String[] ids) throws Exception {
275                    long companyId = GetterUtil.getLong(ids[0]);
276    
277                    reindexNodes(companyId);
278            }
279    
280            @Override
281            protected String getPortletId(SearchContext searchContext) {
282                    return PORTLET_ID;
283            }
284    
285            protected void reindexAttachments(WikiPage page)
286                    throws PortalException, SystemException {
287    
288                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
289                            DLFileEntry.class);
290    
291                    for (FileEntry attachmentsFileEntry :
292                                    page.getAttachmentsFileEntries()) {
293    
294                            indexer.reindex((DLFileEntry)attachmentsFileEntry.getModel());
295                    }
296            }
297    
298            protected void reindexNodes(final long companyId)
299                    throws PortalException, SystemException {
300    
301                    ActionableDynamicQuery actionableDynamicQuery =
302                            new WikiNodeActionableDynamicQuery() {
303    
304                            @Override
305                            protected void performAction(Object object)
306                                    throws PortalException, SystemException {
307    
308                                    WikiNode node = (WikiNode)object;
309    
310                                    reindexPages(companyId, node.getGroupId(), node.getNodeId());
311                            }
312    
313                    };
314    
315                    actionableDynamicQuery.setCompanyId(companyId);
316    
317                    actionableDynamicQuery.performActions();
318            }
319    
320            protected void reindexPages(long companyId, long groupId, final long nodeId)
321                    throws PortalException, SystemException {
322    
323                    ActionableDynamicQuery actionableDynamicQuery =
324                            new WikiPageActionableDynamicQuery() {
325    
326                            @Override
327                            protected void addCriteria(DynamicQuery dynamicQuery) {
328                                    Property nodeIdProperty = PropertyFactoryUtil.forName("nodeId");
329    
330                                    dynamicQuery.add(nodeIdProperty.eq(nodeId));
331    
332                                    Property headProperty = PropertyFactoryUtil.forName("head");
333    
334                                    dynamicQuery.add(headProperty.eq(true));
335                            }
336    
337                            @Override
338                            protected void performAction(Object object) {
339                                    WikiPage page = (WikiPage)object;
340    
341                                    try {
342                                            Document document = getDocument(page);
343    
344                                            addDocument(document);
345                                    }
346                                    catch (PortalException pe) {
347                                            if (_log.isWarnEnabled()) {
348                                                    _log.warn(
349                                                            "Unable to index wiki page " + page.getPageId(),
350                                                            pe);
351                                            }
352                                    }
353                            }
354    
355                    };
356    
357                    actionableDynamicQuery.setCompanyId(companyId);
358                    actionableDynamicQuery.setGroupId(groupId);
359                    actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
360    
361                    actionableDynamicQuery.performActions();
362            }
363    
364            private static Log _log = LogFactoryUtil.getLog(WikiPageIndexer.class);
365    
366    }