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