1
14
15 package com.liferay.portlet.journal.util;
16
17 import com.liferay.portal.kernel.log.Log;
18 import com.liferay.portal.kernel.log.LogFactoryUtil;
19 import com.liferay.portal.kernel.search.BaseIndexer;
20 import com.liferay.portal.kernel.search.Document;
21 import com.liferay.portal.kernel.search.DocumentImpl;
22 import com.liferay.portal.kernel.search.Field;
23 import com.liferay.portal.kernel.search.Indexer;
24 import com.liferay.portal.kernel.search.SearchContext;
25 import com.liferay.portal.kernel.search.SearchEngineUtil;
26 import com.liferay.portal.kernel.search.Summary;
27 import com.liferay.portal.kernel.util.GetterUtil;
28 import com.liferay.portal.kernel.util.HtmlUtil;
29 import com.liferay.portal.kernel.util.StringBundler;
30 import com.liferay.portal.kernel.util.StringPool;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Validator;
33 import com.liferay.portal.kernel.workflow.WorkflowConstants;
34 import com.liferay.portal.kernel.xml.Element;
35 import com.liferay.portal.kernel.xml.SAXReaderUtil;
36 import com.liferay.portal.util.PortletKeys;
37 import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
38 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
39 import com.liferay.portlet.expando.model.ExpandoBridge;
40 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
41 import com.liferay.portlet.journal.model.JournalArticle;
42 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
43
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Date;
47 import java.util.LinkedList;
48 import java.util.List;
49
50 import javax.portlet.PortletURL;
51
52
60 public class JournalIndexer extends BaseIndexer {
61
62 public static final String[] CLASS_NAMES = {JournalArticle.class.getName()};
63
64 public static final String PORTLET_ID = PortletKeys.JOURNAL;
65
66 public String[] getClassNames() {
67 return CLASS_NAMES;
68 }
69
70 public Summary getSummary(
71 Document document, String snippet, PortletURL portletURL) {
72
73 String title = document.get(Field.TITLE);
74
75 String content = snippet;
76
77 if (Validator.isNull(snippet)) {
78 content = StringUtil.shorten(document.get(Field.CONTENT), 200);
79 }
80
81 String groupId = document.get("groupId");
82 String articleId = document.get(Field.ENTRY_CLASS_PK);
83 String version = document.get("version");
84
85 portletURL.setParameter("struts_action", "/journal/edit_article");
86 portletURL.setParameter("groupId", groupId);
87 portletURL.setParameter("articleId", articleId);
88 portletURL.setParameter("version", version);
89
90 return new Summary(title, content, portletURL);
91 }
92
93 protected void doDelete(Object obj) throws Exception {
94 JournalArticle article = (JournalArticle)obj;
95
96 Document document = new DocumentImpl();
97
98 document.addUID(
99 PORTLET_ID, article.getGroupId(), article.getArticleId());
100
101 SearchEngineUtil.deleteDocument(
102 article.getCompanyId(), document.get(Field.UID));
103 }
104
105 protected Document doGetDocument(Object obj) throws Exception {
106 JournalArticle article = (JournalArticle)obj;
107
108 long companyId = article.getCompanyId();
109 long groupId = getParentGroupId(article.getGroupId());
110 long scopeGroupId = article.getGroupId();
111 long userId = article.getUserId();
112 long resourcePrimKey = article.getResourcePrimKey();
113 String articleId = article.getArticleId();
114 double version = article.getVersion();
115 String title = article.getTitle();
116 String description = article.getDescription();
117 String content = article.getContent();
118 String type = article.getType();
119 Date displayDate = article.getDisplayDate();
120
121 long[] assetCategoryIds = AssetCategoryLocalServiceUtil.getCategoryIds(
122 JournalArticle.class.getName(), resourcePrimKey);
123 String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
124 JournalArticle.class.getName(), resourcePrimKey);
125
126 ExpandoBridge expandoBridge = article.getExpandoBridge();
127
128 Document document = new DocumentImpl();
129
130 document.addUID(PORTLET_ID, groupId, articleId);
131
132 document.addModifiedDate(displayDate);
133
134 document.addKeyword(Field.COMPANY_ID, companyId);
135 document.addKeyword(Field.PORTLET_ID, PORTLET_ID);
136 document.addKeyword(Field.GROUP_ID, groupId);
137 document.addKeyword(Field.SCOPE_GROUP_ID, scopeGroupId);
138 document.addKeyword(Field.USER_ID, userId);
139
140 document.addText(Field.TITLE, title);
141 document.addText(Field.CONTENT, processContent(document, content));
142 document.addText(Field.DESCRIPTION, description);
143 document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
144 document.addKeyword(Field.ASSET_TAG_NAMES, assetTagNames);
145
146 document.addKeyword(
147 Field.ENTRY_CLASS_NAME, JournalArticle.class.getName());
148 document.addKeyword(Field.ENTRY_CLASS_PK, articleId);
149 document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);
150 document.addKeyword(Field.VERSION, version);
151 document.addKeyword(Field.TYPE, type);
152
153 ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
154
155 return document;
156 }
157
158 protected void doReindex(Object obj) throws Exception {
159 JournalArticle article = (JournalArticle)obj;
160
161 if (!article.isApproved() || !article.isIndexable()) {
162 return;
163 }
164
165 Document document = getDocument(article);
166
167 SearchEngineUtil.updateDocument(article.getCompanyId(), document);
168 }
169
170 protected void doReindex(String className, long classPK) throws Exception {
171 JournalArticle article =
172 JournalArticleLocalServiceUtil.getLatestArticle(
173 classPK, WorkflowConstants.STATUS_APPROVED);
174
175 doReindex(article);
176 }
177
178 protected void doReindex(String[] ids) throws Exception {
179 long companyId = GetterUtil.getLong(ids[0]);
180
181 reindexArticles(companyId);
182 }
183
184 protected String encodeFieldName(String name) {
185 return _FIELD_NAMESPACE.concat(StringPool.FORWARD_SLASH).concat(name);
186 }
187
188 protected String getIndexableContent(Document document, Element rootElement)
189 throws Exception {
190
191 StringBundler sb = new StringBundler();
192
193 LinkedList<Element> queue = new LinkedList<Element>(
194 rootElement.elements());
195
196 Element element = null;
197
198 while ((element = queue.poll()) != null) {
199 String elType = element.attributeValue("type", StringPool.BLANK);
200 String elIndexType = element.attributeValue(
201 "index-type", StringPool.BLANK);
202
203 indexField(document, element, elType, elIndexType);
204
205 if (elType.equals("text") || elType.equals("text_box") ||
206 elType.equals("text_area")) {
207
208 for (Element dynamicContentElement :
209 element.elements("dynamic-content")) {
210
211 String text = dynamicContentElement.getText();
212
213 sb.append(text);
214 sb.append(StringPool.SPACE);
215 }
216 }
217 else if (element.getName().equals("static-content")) {
218 String text = element.getText();
219
220 sb.append(text);
221 sb.append(StringPool.SPACE);
222 }
223
224 queue.addAll(element.elements());
225 }
226
227 return sb.toString();
228 }
229
230 protected String getIndexableContent(Document document, String content) {
231 try {
232 com.liferay.portal.kernel.xml.Document contentDocument =
233 SAXReaderUtil.read(content);
234
235 Element rootElement = contentDocument.getRootElement();
236
237 return getIndexableContent(document, rootElement);
238 }
239 catch (Exception e) {
240 _log.error(e, e);
241
242 return content;
243 }
244 }
245
246 protected String getPortletId(SearchContext searchContext) {
247 return PORTLET_ID;
248 }
249
250 protected void indexField(
251 Document document, Element element, String elType, String elIndexType) {
252
253 if (Validator.isNull(elIndexType)) {
254 return;
255 }
256
257 Element dynamicContentElement = element.element("dynamic-content");
258
259 String fieldName = encodeFieldName(
260 element.attributeValue("name", StringPool.BLANK));
261 String[] value = new String[] {dynamicContentElement.getText()};
262
263 if (elType.equals("multi-list")) {
264 List<Element> optionElements = dynamicContentElement.elements();
265
266 value = new String[optionElements.size()];
267
268 for (int i = 0; i < optionElements.size(); i++) {
269 value[i] = optionElements.get(i).getText();
270 }
271 }
272
273 if (elIndexType.equals("keyword")) {
274 document.addKeyword(fieldName, value);
275 }
276 else if (elIndexType.equals("text")) {
277 document.addText(
278 fieldName, StringUtil.merge(value, StringPool.SPACE));
279 }
280 }
281
282 protected String processContent(Document document, String content) {
283 if ((content != null) &&
284 ((content.indexOf("<dynamic-content") != -1) ||
285 (content.indexOf("<static-content") != -1))) {
286
287 content = getIndexableContent(document, content);
288
289 content = StringUtil.replace(
290 content, "<![CDATA[", StringPool.BLANK);
291 content = StringUtil.replace(content, "]]>", StringPool.BLANK);
292 }
293
294 content = StringUtil.replace(content, "&", "&");
295 content = StringUtil.replace(content, "<", "<");
296 content = StringUtil.replace(content, ">", ">");
297
298 content = HtmlUtil.extractText(content);
299
300 return content;
301 }
302
303 protected void reindexArticles(long companyId) throws Exception {
304 int count = JournalArticleLocalServiceUtil.getCompanyArticlesCount(
305 companyId, WorkflowConstants.STATUS_APPROVED);
306
307 int pages = count / Indexer.DEFAULT_INTERVAL;
308
309 for (int i = 0; i <= pages; i++) {
310 int start = (i * Indexer.DEFAULT_INTERVAL);
311 int end = start + Indexer.DEFAULT_INTERVAL;
312
313 reindexArticles(companyId, start, end);
314 }
315 }
316
317 protected void reindexArticles(long companyId, int start, int end)
318 throws Exception {
319
320 List<JournalArticle> articles =
321 JournalArticleLocalServiceUtil.getCompanyArticles(
322 companyId, WorkflowConstants.STATUS_APPROVED, start, end);
323
324 if (articles.isEmpty()) {
325 return;
326 }
327
328 Collection<Document> documents = new ArrayList<Document>();
329
330 for (JournalArticle article : articles) {
331 Document document = getDocument(article);
332
333 documents.add(document);
334 }
335
336 SearchEngineUtil.updateDocuments(companyId, documents);
337 }
338
339 protected static final String _FIELD_NAMESPACE = "web_content";
340
341 private static Log _log = LogFactoryUtil.getLog(JournalIndexer.class);
342
343 }