001    /**
002     * Copyright (c) 2000-2012 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.QueryUtil;
018    import com.liferay.portal.kernel.search.BaseIndexer;
019    import com.liferay.portal.kernel.search.BooleanClauseOccur;
020    import com.liferay.portal.kernel.search.BooleanQuery;
021    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
022    import com.liferay.portal.kernel.search.Document;
023    import com.liferay.portal.kernel.search.DocumentImpl;
024    import com.liferay.portal.kernel.search.Field;
025    import com.liferay.portal.kernel.search.Hits;
026    import com.liferay.portal.kernel.search.Indexer;
027    import com.liferay.portal.kernel.search.SearchContext;
028    import com.liferay.portal.kernel.search.SearchEngineUtil;
029    import com.liferay.portal.kernel.search.Summary;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.HtmlUtil;
032    import com.liferay.portal.kernel.util.StringUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.kernel.workflow.WorkflowConstants;
035    import com.liferay.portal.util.PortletKeys;
036    import com.liferay.portlet.wiki.model.WikiNode;
037    import com.liferay.portlet.wiki.model.WikiPage;
038    import com.liferay.portlet.wiki.service.WikiNodeLocalServiceUtil;
039    import com.liferay.portlet.wiki.service.WikiNodeServiceUtil;
040    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
041    
042    import java.util.ArrayList;
043    import java.util.Collection;
044    import java.util.List;
045    import java.util.Locale;
046    
047    import javax.portlet.PortletURL;
048    
049    /**
050     * @author Brian Wing Shun Chan
051     * @author Harry Mark
052     * @author Bruno Farache
053     * @author Raymond Augé
054     */
055    public class WikiIndexer extends BaseIndexer {
056    
057            public static final String[] CLASS_NAMES = {WikiPage.class.getName()};
058    
059            public static final String PORTLET_ID = PortletKeys.WIKI;
060    
061            public String[] getClassNames() {
062                    return CLASS_NAMES;
063            }
064    
065            public String getPortletId() {
066                    return PORTLET_ID;
067            }
068    
069            @Override
070            public boolean isPermissionAware() {
071                    return _PERMISSION_AWARE;
072            }
073    
074            @Override
075            public void postProcessContextQuery(
076                            BooleanQuery contextQuery, SearchContext searchContext)
077                    throws Exception {
078    
079                    int status = GetterUtil.getInteger(
080                            searchContext.getAttribute(Field.STATUS),
081                            WorkflowConstants.STATUS_ANY);
082    
083                    if (status != WorkflowConstants.STATUS_ANY) {
084                            contextQuery.addRequiredTerm(Field.STATUS, status);
085                    }
086    
087                    long[] nodeIds = searchContext.getNodeIds();
088    
089                    if ((nodeIds != null) && (nodeIds.length > 0)) {
090                            BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create(
091                                    searchContext);
092    
093                            for (long nodeId : nodeIds) {
094                                    try {
095                                            WikiNodeServiceUtil.getNode(nodeId);
096                                    }
097                                    catch (Exception e) {
098                                            continue;
099                                    }
100    
101                                    nodeIdsQuery.addTerm(Field.NODE_ID, nodeId);
102                            }
103    
104                            contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
105                    }
106            }
107    
108            @Override
109            protected void doDelete(Object obj) throws Exception {
110                    SearchContext searchContext = new SearchContext();
111    
112                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
113    
114                    if (obj instanceof Object[]) {
115                            Object[] array = (Object[])obj;
116    
117                            long companyId = (Long)array[0];
118                            long nodeId = (Long)array[1];
119                            String title = (String)array[2];
120    
121                            Document document = new DocumentImpl();
122    
123                            document.addUID(PORTLET_ID, nodeId, title);
124    
125                            SearchEngineUtil.deleteDocument(companyId, document.get(Field.UID));
126    
127                    }
128                    else if (obj instanceof WikiNode) {
129                            WikiNode node = (WikiNode)obj;
130    
131                            BooleanQuery booleanQuery = BooleanQueryFactoryUtil.create(
132                                    searchContext);
133    
134                            booleanQuery.addRequiredTerm(Field.PORTLET_ID, PORTLET_ID);
135    
136                            booleanQuery.addRequiredTerm("nodeId", node.getNodeId());
137    
138                            Hits hits = SearchEngineUtil.search(
139                                    node.getCompanyId(), booleanQuery, QueryUtil.ALL_POS,
140                                    QueryUtil.ALL_POS);
141    
142                            for (int i = 0; i < hits.getLength(); i++) {
143                                    Document document = hits.doc(i);
144    
145                                    SearchEngineUtil.deleteDocument(
146                                            node.getCompanyId(), document.get(Field.UID));
147                            }
148                    }
149                    else if (obj instanceof WikiPage) {
150                            WikiPage page = (WikiPage)obj;
151    
152                            Document document = new DocumentImpl();
153    
154                            document.addUID(PORTLET_ID, page.getNodeId(), page.getTitle());
155    
156                            SearchEngineUtil.deleteDocument(
157                                    page.getCompanyId(), document.get(Field.UID));
158                    }
159            }
160    
161            @Override
162            protected Document doGetDocument(Object obj) throws Exception {
163                    WikiPage page = (WikiPage)obj;
164    
165                    Document document = getBaseModelDocument(PORTLET_ID, page);
166    
167                    document.addUID(PORTLET_ID, page.getNodeId(), page.getTitle());
168    
169                    String content = HtmlUtil.extractText(
170                            WikiUtil.convert(page, null, null, null));
171    
172                    document.addText(Field.CONTENT, content);
173    
174                    document.addKeyword(Field.NODE_ID, page.getNodeId());
175                    document.addText(Field.TITLE, page.getTitle());
176    
177                    return document;
178            }
179    
180            @Override
181            protected Summary doGetSummary(
182                    Document document, Locale locale, String snippet,
183                    PortletURL portletURL) {
184    
185                    String title = document.get(Field.TITLE);
186    
187                    String content = snippet;
188    
189                    if (Validator.isNull(snippet)) {
190                            content = StringUtil.shorten(document.get(Field.CONTENT), 200);
191                    }
192    
193                    String nodeId = document.get("nodeId");
194    
195                    portletURL.setParameter("struts_action", "/wiki/view");
196                    portletURL.setParameter("nodeId", nodeId);
197                    portletURL.setParameter("title", title);
198    
199                    return new Summary(title, content, portletURL);
200            }
201    
202            @Override
203            protected void doReindex(Object obj) throws Exception {
204                    WikiPage page = (WikiPage)obj;
205    
206                    if (Validator.isNotNull(page.getRedirectTitle())) {
207                            return;
208                    }
209    
210                    Document document = getDocument(page);
211    
212                    SearchEngineUtil.updateDocument(page.getCompanyId(), document);
213            }
214    
215            @Override
216            protected void doReindex(String className, long classPK) throws Exception {
217                    WikiPage page = WikiPageLocalServiceUtil.getPage(classPK);
218    
219                    doReindex(page);
220            }
221    
222            @Override
223            protected void doReindex(String[] ids) throws Exception {
224                    long companyId = GetterUtil.getLong(ids[0]);
225    
226                    reindexNodes(companyId);
227            }
228    
229            @Override
230            protected String getPortletId(SearchContext searchContext) {
231                    return PORTLET_ID;
232            }
233    
234            protected void reindexNodes(long companyId) throws Exception {
235                    int nodeCount = WikiNodeLocalServiceUtil.getCompanyNodesCount(
236                            companyId);
237    
238                    int nodePages = nodeCount / Indexer.DEFAULT_INTERVAL;
239    
240                    for (int i = 0; i <= nodePages; i++) {
241                            int nodeStart = (i * Indexer.DEFAULT_INTERVAL);
242                            int nodeEnd = nodeStart + Indexer.DEFAULT_INTERVAL;
243    
244                            reindexNodes(companyId, nodeStart, nodeEnd);
245                    }
246            }
247    
248            protected void reindexNodes(long companyId, int nodeStart, int nodeEnd)
249                    throws Exception {
250    
251                    List<WikiNode> nodes = WikiNodeLocalServiceUtil.getCompanyNodes(
252                            companyId, nodeStart, nodeEnd);
253    
254                    for (WikiNode node : nodes) {
255                            long nodeId = node.getNodeId();
256    
257                            int pageCount = WikiPageLocalServiceUtil.getPagesCount(
258                                    nodeId, true);
259    
260                            int pagePages = pageCount / Indexer.DEFAULT_INTERVAL;
261    
262                            for (int i = 0; i <= pagePages; i++) {
263                                    int pageStart = (i * Indexer.DEFAULT_INTERVAL);
264                                    int pageEnd = pageStart + Indexer.DEFAULT_INTERVAL;
265    
266                                    reindexPages(companyId, nodeId, pageStart, pageEnd);
267                            }
268                    }
269            }
270    
271            protected void reindexPages(
272                            long companyId, long nodeId, int pageStart, int pageEnd)
273                    throws Exception {
274    
275                    List<WikiPage> pages = WikiPageLocalServiceUtil.getPages(
276                            nodeId, true, pageStart, pageEnd);
277    
278                    if (pages.isEmpty()) {
279                            return;
280                    }
281    
282                    Collection<Document> documents = new ArrayList<Document>();
283    
284                    for (WikiPage page : pages) {
285                            Document document = getDocument(page);
286    
287                            documents.add(document);
288                    }
289    
290                    SearchEngineUtil.updateDocuments(companyId, documents);
291            }
292    
293            private static final boolean _PERMISSION_AWARE = true;
294    
295    }