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