001
014
015 package com.liferay.portlet.journal.util;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.search.BaseIndexer;
020 import com.liferay.portal.kernel.search.Document;
021 import com.liferay.portal.kernel.search.DocumentImpl;
022 import com.liferay.portal.kernel.search.Field;
023 import com.liferay.portal.kernel.search.Indexer;
024 import com.liferay.portal.kernel.search.SearchContext;
025 import com.liferay.portal.kernel.search.SearchEngineUtil;
026 import com.liferay.portal.kernel.search.Summary;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.HtmlUtil;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.util.Validator;
033 import com.liferay.portal.kernel.workflow.WorkflowConstants;
034 import com.liferay.portal.kernel.xml.Element;
035 import com.liferay.portal.kernel.xml.SAXReaderUtil;
036 import com.liferay.portal.util.PortletKeys;
037 import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
038 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
039 import com.liferay.portlet.expando.model.ExpandoBridge;
040 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
041 import com.liferay.portlet.journal.model.JournalArticle;
042 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
043
044 import java.util.ArrayList;
045 import java.util.Collection;
046 import java.util.Date;
047 import java.util.LinkedList;
048 import java.util.List;
049
050 import javax.portlet.PortletURL;
051
052
058 public class JournalIndexer extends BaseIndexer {
059
060 public static final String[] CLASS_NAMES = {JournalArticle.class.getName()};
061
062 public static final String PORTLET_ID = PortletKeys.JOURNAL;
063
064 public String[] getClassNames() {
065 return CLASS_NAMES;
066 }
067
068 public Summary getSummary(
069 Document document, String snippet, PortletURL portletURL) {
070
071 String title = document.get(Field.TITLE);
072
073 String content = snippet;
074
075 if (Validator.isNull(snippet)) {
076 content = StringUtil.shorten(document.get(Field.CONTENT), 200);
077 }
078
079 String groupId = document.get("groupId");
080 String articleId = document.get(Field.ENTRY_CLASS_PK);
081 String version = document.get("version");
082
083 portletURL.setParameter("struts_action", "/journal/edit_article");
084 portletURL.setParameter("groupId", groupId);
085 portletURL.setParameter("articleId", articleId);
086 portletURL.setParameter("version", version);
087
088 return new Summary(title, content, portletURL);
089 }
090
091 protected void doDelete(Object obj) throws Exception {
092 JournalArticle article = (JournalArticle)obj;
093
094 Document document = new DocumentImpl();
095
096 document.addUID(
097 PORTLET_ID, article.getGroupId(), article.getArticleId());
098
099 SearchEngineUtil.deleteDocument(
100 article.getCompanyId(), document.get(Field.UID));
101 }
102
103 protected Document doGetDocument(Object obj) throws Exception {
104 JournalArticle article = (JournalArticle)obj;
105
106 long companyId = article.getCompanyId();
107 long groupId = getParentGroupId(article.getGroupId());
108 long scopeGroupId = article.getGroupId();
109 long userId = article.getUserId();
110 long resourcePrimKey = article.getResourcePrimKey();
111 String articleId = article.getArticleId();
112 double version = article.getVersion();
113 String title = article.getTitle();
114 String description = article.getDescription();
115 String content = article.getContent();
116 String type = article.getType();
117 Date displayDate = article.getDisplayDate();
118
119 long[] assetCategoryIds = AssetCategoryLocalServiceUtil.getCategoryIds(
120 JournalArticle.class.getName(), resourcePrimKey);
121 String[] assetCategoryNames =
122 AssetCategoryLocalServiceUtil.getCategoryNames(
123 JournalArticle.class.getName(), resourcePrimKey);
124 String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
125 JournalArticle.class.getName(), resourcePrimKey);
126
127 ExpandoBridge expandoBridge = article.getExpandoBridge();
128
129 Document document = new DocumentImpl();
130
131 document.addUID(PORTLET_ID, groupId, articleId);
132
133 document.addModifiedDate(displayDate);
134
135 document.addKeyword(Field.COMPANY_ID, companyId);
136 document.addKeyword(Field.PORTLET_ID, PORTLET_ID);
137 document.addKeyword(Field.GROUP_ID, groupId);
138 document.addKeyword(Field.SCOPE_GROUP_ID, scopeGroupId);
139 document.addKeyword(Field.USER_ID, userId);
140
141 document.addText(Field.TITLE, title);
142 document.addText(Field.CONTENT, processContent(document, content));
143 document.addText(Field.DESCRIPTION, description);
144 document.addKeyword(Field.ASSET_CATEGORY_IDS, assetCategoryIds);
145 document.addKeyword(Field.ASSET_CATEGORY_NAMES, assetCategoryNames);
146 document.addKeyword(Field.ASSET_TAG_NAMES, assetTagNames);
147
148 document.addKeyword(
149 Field.ENTRY_CLASS_NAME, JournalArticle.class.getName());
150 document.addKeyword(Field.ENTRY_CLASS_PK, articleId);
151 document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, resourcePrimKey);
152 document.addKeyword(Field.VERSION, version);
153 document.addKeyword(Field.TYPE, type);
154
155 ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
156
157 return document;
158 }
159
160 protected void doReindex(Object obj) throws Exception {
161 JournalArticle article = (JournalArticle)obj;
162
163 if (!article.isApproved() || !article.isIndexable()) {
164 return;
165 }
166
167 Document document = getDocument(article);
168
169 SearchEngineUtil.updateDocument(article.getCompanyId(), document);
170 }
171
172 protected void doReindex(String className, long classPK) throws Exception {
173 JournalArticle article =
174 JournalArticleLocalServiceUtil.getLatestArticle(
175 classPK, WorkflowConstants.STATUS_APPROVED);
176
177 doReindex(article);
178 }
179
180 protected void doReindex(String[] ids) throws Exception {
181 long companyId = GetterUtil.getLong(ids[0]);
182
183 reindexArticles(companyId);
184 }
185
186 protected String encodeFieldName(String name) {
187 return _FIELD_NAMESPACE.concat(StringPool.FORWARD_SLASH).concat(name);
188 }
189
190 protected String getIndexableContent(Document document, Element rootElement)
191 throws Exception {
192
193 StringBundler sb = new StringBundler();
194
195 LinkedList<Element> queue = new LinkedList<Element>(
196 rootElement.elements());
197
198 Element element = null;
199
200 while ((element = queue.poll()) != null) {
201 String elType = element.attributeValue("type", StringPool.BLANK);
202 String elIndexType = element.attributeValue(
203 "index-type", StringPool.BLANK);
204
205 indexField(document, element, elType, elIndexType);
206
207 if (elType.equals("text") || elType.equals("text_box") ||
208 elType.equals("text_area")) {
209
210 for (Element dynamicContentElement :
211 element.elements("dynamic-content")) {
212
213 String text = dynamicContentElement.getText();
214
215 sb.append(text);
216 sb.append(StringPool.SPACE);
217 }
218 }
219 else if (element.getName().equals("static-content")) {
220 String text = element.getText();
221
222 sb.append(text);
223 sb.append(StringPool.SPACE);
224 }
225
226 queue.addAll(element.elements());
227 }
228
229 return sb.toString();
230 }
231
232 protected String getIndexableContent(Document document, String content) {
233 try {
234 com.liferay.portal.kernel.xml.Document contentDocument =
235 SAXReaderUtil.read(content);
236
237 Element rootElement = contentDocument.getRootElement();
238
239 return getIndexableContent(document, rootElement);
240 }
241 catch (Exception e) {
242 _log.error(e, e);
243
244 return content;
245 }
246 }
247
248 protected String getPortletId(SearchContext searchContext) {
249 return PORTLET_ID;
250 }
251
252 protected void indexField(
253 Document document, Element element, String elType, String elIndexType) {
254
255 if (Validator.isNull(elIndexType)) {
256 return;
257 }
258
259 Element dynamicContentElement = element.element("dynamic-content");
260
261 String fieldName = encodeFieldName(
262 element.attributeValue("name", StringPool.BLANK));
263 String[] value = new String[] {dynamicContentElement.getText()};
264
265 if (elType.equals("multi-list")) {
266 List<Element> optionElements = dynamicContentElement.elements();
267
268 value = new String[optionElements.size()];
269
270 for (int i = 0; i < optionElements.size(); i++) {
271 value[i] = optionElements.get(i).getText();
272 }
273 }
274
275 if (elIndexType.equals("keyword")) {
276 document.addKeyword(fieldName, value);
277 }
278 else if (elIndexType.equals("text")) {
279 document.addText(
280 fieldName, StringUtil.merge(value, StringPool.SPACE));
281 }
282 }
283
284 protected String processContent(Document document, String content) {
285 if ((content != null) &&
286 ((content.indexOf("<dynamic-content") != -1) ||
287 (content.indexOf("<static-content") != -1))) {
288
289 content = getIndexableContent(document, content);
290
291 content = StringUtil.replace(
292 content, "<![CDATA[", StringPool.BLANK);
293 content = StringUtil.replace(content, "]]>", StringPool.BLANK);
294 }
295
296 content = StringUtil.replace(content, "&", "&");
297 content = StringUtil.replace(content, "<", "<");
298 content = StringUtil.replace(content, ">", ">");
299
300 content = HtmlUtil.extractText(content);
301
302 return content;
303 }
304
305 protected void reindexArticles(long companyId) throws Exception {
306 int count = JournalArticleLocalServiceUtil.getCompanyArticlesCount(
307 companyId, WorkflowConstants.STATUS_APPROVED);
308
309 int pages = count / Indexer.DEFAULT_INTERVAL;
310
311 for (int i = 0; i <= pages; i++) {
312 int start = (i * Indexer.DEFAULT_INTERVAL);
313 int end = start + Indexer.DEFAULT_INTERVAL;
314
315 reindexArticles(companyId, start, end);
316 }
317 }
318
319 protected void reindexArticles(long companyId, int start, int end)
320 throws Exception {
321
322 List<JournalArticle> articles =
323 JournalArticleLocalServiceUtil.getCompanyArticles(
324 companyId, WorkflowConstants.STATUS_APPROVED, start, end);
325
326 if (articles.isEmpty()) {
327 return;
328 }
329
330 Collection<Document> documents = new ArrayList<Document>();
331
332 for (JournalArticle article : articles) {
333 Document document = getDocument(article);
334
335 documents.add(document);
336 }
337
338 SearchEngineUtil.updateDocuments(companyId, documents);
339 }
340
341 protected static final String _FIELD_NAMESPACE = "web_content";
342
343 private static Log _log = LogFactoryUtil.getLog(JournalIndexer.class);
344
345 }