001    /**
002     * Copyright (c) 2000-2011 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.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 void postProcessContextQuery(
071                            BooleanQuery contextQuery, SearchContext searchContext)
072                    throws Exception {
073    
074                    int status = GetterUtil.getInteger(
075                            searchContext.getAttribute(Field.STATUS),
076                            WorkflowConstants.STATUS_ANY);
077    
078                    if (status != WorkflowConstants.STATUS_ANY) {
079                            contextQuery.addRequiredTerm(Field.STATUS, status);
080                    }
081    
082                    long[] nodeIds = searchContext.getNodeIds();
083    
084                    if ((nodeIds != null) && (nodeIds.length > 0)) {
085                            BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create(
086                                    searchContext);
087    
088                            for (long nodeId : nodeIds) {
089                                    try {
090                                            WikiNodeServiceUtil.getNode(nodeId);
091                                    }
092                                    catch (Exception e) {
093                                            continue;
094                                    }
095    
096                                    nodeIdsQuery.addTerm(Field.NODE_ID, nodeId);
097                            }
098    
099                            contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
100                    }
101            }
102    
103            @Override
104            protected void doDelete(Object obj) throws Exception {
105                    SearchContext searchContext = new SearchContext();
106    
107                    searchContext.setSearchEngineId(SearchEngineUtil.SYSTEM_ENGINE_ID);
108    
109                    if (obj instanceof Object[]) {
110                            Object[] array = (Object[])obj;
111    
112                            long companyId = (Long)array[0];
113                            long nodeId = (Long)array[1];
114                            String title = (String)array[2];
115    
116                            Document document = new DocumentImpl();
117    
118                            document.addUID(PORTLET_ID, nodeId, title);
119    
120                            SearchEngineUtil.deleteDocument(companyId, document.get(Field.UID));
121    
122                    }
123                    else if (obj instanceof WikiNode) {
124                            WikiNode node = (WikiNode)obj;
125    
126                            BooleanQuery booleanQuery = BooleanQueryFactoryUtil.create(
127                                    searchContext);
128    
129                            booleanQuery.addRequiredTerm(Field.PORTLET_ID, PORTLET_ID);
130    
131                            booleanQuery.addRequiredTerm("nodeId", node.getNodeId());
132    
133                            Hits hits = SearchEngineUtil.search(
134                                    node.getCompanyId(), booleanQuery, QueryUtil.ALL_POS,
135                                    QueryUtil.ALL_POS);
136    
137                            for (int i = 0; i < hits.getLength(); i++) {
138                                    Document document = hits.doc(i);
139    
140                                    SearchEngineUtil.deleteDocument(
141                                            node.getCompanyId(), document.get(Field.UID));
142                            }
143                    }
144                    else if (obj instanceof WikiPage) {
145                            WikiPage page = (WikiPage)obj;
146    
147                            Document document = new DocumentImpl();
148    
149                            document.addUID(PORTLET_ID, page.getNodeId(), page.getTitle());
150    
151                            SearchEngineUtil.deleteDocument(
152                                    page.getCompanyId(), document.get(Field.UID));
153                    }
154            }
155    
156            @Override
157            protected Document doGetDocument(Object obj) throws Exception {
158                    WikiPage page = (WikiPage)obj;
159    
160                    Document document = getBaseModelDocument(PORTLET_ID, page);
161    
162                    document.addUID(PORTLET_ID, page.getNodeId(), page.getTitle());
163    
164                    String content = HtmlUtil.extractText(
165                            WikiUtil.convert(page, null, null, null));
166    
167                    document.addText(Field.CONTENT, content);
168    
169                    document.addKeyword(Field.NODE_ID, page.getNodeId());
170                    document.addText(Field.TITLE, page.getTitle());
171    
172                    return document;
173            }
174    
175            @Override
176            protected Summary doGetSummary(
177                    Document document, Locale locale, String snippet,
178                    PortletURL portletURL) {
179    
180                    String title = document.get(Field.TITLE);
181    
182                    String content = snippet;
183    
184                    if (Validator.isNull(snippet)) {
185                            content = StringUtil.shorten(document.get(Field.CONTENT), 200);
186                    }
187    
188                    String nodeId = document.get("nodeId");
189    
190                    portletURL.setParameter("struts_action", "/wiki/view");
191                    portletURL.setParameter("nodeId", nodeId);
192                    portletURL.setParameter("title", title);
193    
194                    return new Summary(title, content, portletURL);
195            }
196    
197            @Override
198            protected void doReindex(Object obj) throws Exception {
199                    WikiPage page = (WikiPage)obj;
200    
201                    if (Validator.isNotNull(page.getRedirectTitle())) {
202                            return;
203                    }
204    
205                    Document document = getDocument(page);
206    
207                    SearchEngineUtil.updateDocument(page.getCompanyId(), document);
208            }
209    
210            @Override
211            protected void doReindex(String className, long classPK) throws Exception {
212                    WikiPage page = WikiPageLocalServiceUtil.getPage(classPK);
213    
214                    doReindex(page);
215            }
216    
217            @Override
218            protected void doReindex(String[] ids) throws Exception {
219                    long companyId = GetterUtil.getLong(ids[0]);
220    
221                    reindexNodes(companyId);
222            }
223    
224            @Override
225            protected String getPortletId(SearchContext searchContext) {
226                    return PORTLET_ID;
227            }
228    
229            protected void reindexNodes(long companyId) throws Exception {
230                    int nodeCount = WikiNodeLocalServiceUtil.getCompanyNodesCount(
231                            companyId);
232    
233                    int nodePages = nodeCount / Indexer.DEFAULT_INTERVAL;
234    
235                    for (int i = 0; i <= nodePages; i++) {
236                            int nodeStart = (i * Indexer.DEFAULT_INTERVAL);
237                            int nodeEnd = nodeStart + Indexer.DEFAULT_INTERVAL;
238    
239                            reindexNodes(companyId, nodeStart, nodeEnd);
240                    }
241            }
242    
243            protected void reindexNodes(long companyId, int nodeStart, int nodeEnd)
244                    throws Exception {
245    
246                    List<WikiNode> nodes = WikiNodeLocalServiceUtil.getCompanyNodes(
247                            companyId, nodeStart, nodeEnd);
248    
249                    for (WikiNode node : nodes) {
250                            long nodeId = node.getNodeId();
251    
252                            int pageCount = WikiPageLocalServiceUtil.getPagesCount(
253                                    nodeId, true);
254    
255                            int pagePages = pageCount / Indexer.DEFAULT_INTERVAL;
256    
257                            for (int i = 0; i <= pagePages; i++) {
258                                    int pageStart = (i * Indexer.DEFAULT_INTERVAL);
259                                    int pageEnd = pageStart + Indexer.DEFAULT_INTERVAL;
260    
261                                    reindexPages(companyId, nodeId, pageStart, pageEnd);
262                            }
263                    }
264            }
265    
266            protected void reindexPages(
267                            long companyId, long nodeId, int pageStart, int pageEnd)
268                    throws Exception {
269    
270                    List<WikiPage> pages = WikiPageLocalServiceUtil.getPages(
271                            nodeId, true, pageStart, pageEnd);
272    
273                    if (pages.isEmpty()) {
274                            return;
275                    }
276    
277                    Collection<Document> documents = new ArrayList<Document>();
278    
279                    for (WikiPage page : pages) {
280                            Document document = getDocument(page);
281    
282                            documents.add(document);
283                    }
284    
285                    SearchEngineUtil.updateDocuments(companyId, documents);
286            }
287    
288    }