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.ArrayUtil;
036    import com.liferay.portal.kernel.util.GetterUtil;
037    import com.liferay.portal.kernel.util.HtmlUtil;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.kernel.workflow.WorkflowConstants;
040    import com.liferay.portal.security.permission.ActionKeys;
041    import com.liferay.portal.security.permission.PermissionChecker;
042    import com.liferay.portal.util.PortalUtil;
043    import com.liferay.portal.util.PortletKeys;
044    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
045    import com.liferay.portlet.messageboards.model.MBMessage;
046    import com.liferay.portlet.wiki.asset.WikiPageAssetRendererFactory;
047    import com.liferay.portlet.wiki.model.WikiNode;
048    import com.liferay.portlet.wiki.model.WikiPage;
049    import com.liferay.portlet.wiki.service.WikiNodeServiceUtil;
050    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
051    import com.liferay.portlet.wiki.service.permission.WikiPagePermission;
052    import com.liferay.portlet.wiki.service.persistence.WikiNodeActionableDynamicQuery;
053    import com.liferay.portlet.wiki.service.persistence.WikiPageActionableDynamicQuery;
054    
055    import java.util.ArrayList;
056    import java.util.Collection;
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                    if (obj instanceof DLFileEntry) {
085                            DLFileEntry dlFileEntry = (DLFileEntry)obj;
086    
087                            page = WikiPageAttachmentsUtil.getPage(
088                                    dlFileEntry.getFileEntryId());
089    
090                            document.addKeyword(
091                                    Field.CLASS_NAME_ID,
092                                    PortalUtil.getClassNameId(WikiPage.class.getName()));
093                            document.addKeyword(Field.CLASS_PK, page.getResourcePrimKey());
094                    }
095                    else if (obj instanceof MBMessage) {
096                            MBMessage message = (MBMessage)obj;
097    
098                            page = WikiPageLocalServiceUtil.getPage(message.getClassPK());
099                    }
100    
101                    document.addKeyword(Field.NODE_ID, page.getNodeId());
102                    document.addKeyword(Field.RELATED_ENTRY, true);
103            }
104    
105            @Override
106            public String[] getClassNames() {
107                    return CLASS_NAMES;
108            }
109    
110            @Override
111            public String getPortletId() {
112                    return PORTLET_ID;
113            }
114    
115            @Override
116            public boolean hasPermission(
117                            PermissionChecker permissionChecker, String entryClassName,
118                            long entryClassPK, String actionId)
119                    throws Exception {
120    
121                    WikiPage page = WikiPageLocalServiceUtil.getPage(entryClassPK);
122    
123                    return WikiPagePermission.contains(
124                            permissionChecker, page, ActionKeys.VIEW);
125            }
126    
127            @Override
128            public void postProcessContextQuery(
129                            BooleanQuery contextQuery, SearchContext searchContext)
130                    throws Exception {
131    
132                    addStatus(contextQuery, searchContext);
133    
134                    long[] nodeIds = searchContext.getNodeIds();
135    
136                    if (ArrayUtil.isNotEmpty(nodeIds)) {
137                            BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create(
138                                    searchContext);
139    
140                            for (long nodeId : nodeIds) {
141                                    try {
142                                            WikiNodeServiceUtil.getNode(nodeId);
143                                    }
144                                    catch (Exception e) {
145                                            continue;
146                                    }
147    
148                                    nodeIdsQuery.addTerm(Field.NODE_ID, nodeId);
149                            }
150    
151                            contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
152                    }
153            }
154    
155            @Override
156            protected void doDelete(Object obj) throws Exception {
157                    SearchContext searchContext = new SearchContext();
158    
159                    searchContext.setSearchEngineId(getSearchEngineId());
160    
161                    if (obj instanceof Object[]) {
162                            Object[] array = (Object[])obj;
163    
164                            long companyId = (Long)array[0];
165                            long nodeId = (Long)array[1];
166                            String title = (String)array[2];
167    
168                            Document document = new DocumentImpl();
169    
170                            document.addUID(PORTLET_ID, nodeId, title);
171    
172                            SearchEngineUtil.deleteDocument(
173                                    getSearchEngineId(), companyId, document.get(Field.UID));
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    }