001    /**
002     * Copyright (c) 2000-2013 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.journal.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.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.search.BaseIndexer;
026    import com.liferay.portal.kernel.search.BooleanClauseOccur;
027    import com.liferay.portal.kernel.search.BooleanQuery;
028    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
029    import com.liferay.portal.kernel.search.Document;
030    import com.liferay.portal.kernel.search.DocumentImpl;
031    import com.liferay.portal.kernel.search.Field;
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.CharPool;
036    import com.liferay.portal.kernel.util.Constants;
037    import com.liferay.portal.kernel.util.GetterUtil;
038    import com.liferay.portal.kernel.util.HtmlUtil;
039    import com.liferay.portal.kernel.util.LocaleUtil;
040    import com.liferay.portal.kernel.util.LocalizationUtil;
041    import com.liferay.portal.kernel.util.StringPool;
042    import com.liferay.portal.kernel.util.StringUtil;
043    import com.liferay.portal.kernel.util.Validator;
044    import com.liferay.portal.kernel.workflow.WorkflowConstants;
045    import com.liferay.portal.security.permission.ActionKeys;
046    import com.liferay.portal.security.permission.PermissionChecker;
047    import com.liferay.portal.util.PortalUtil;
048    import com.liferay.portal.util.PortletKeys;
049    import com.liferay.portal.util.PropsUtil;
050    import com.liferay.portlet.dynamicdatamapping.StructureFieldException;
051    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
052    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
053    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
054    import com.liferay.portlet.dynamicdatamapping.util.DDMIndexerUtil;
055    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
056    import com.liferay.portlet.journal.model.JournalArticle;
057    import com.liferay.portlet.journal.model.JournalArticleDisplay;
058    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
059    import com.liferay.portlet.journal.service.permission.JournalArticlePermission;
060    import com.liferay.portlet.journal.service.persistence.JournalArticleActionableDynamicQuery;
061    import com.liferay.portlet.trash.util.TrashUtil;
062    
063    import java.io.Serializable;
064    
065    import java.util.ArrayList;
066    import java.util.Collection;
067    import java.util.LinkedHashMap;
068    import java.util.List;
069    import java.util.Locale;
070    
071    import javax.portlet.PortletURL;
072    
073    /**
074     * @author Brian Wing Shun Chan
075     * @author Harry Mark
076     * @author Bruno Farache
077     * @author Raymond Augé
078     * @author Hugo Huijser
079     * @author Tibor Lipusz
080     */
081    public class JournalArticleIndexer extends BaseIndexer {
082    
083            public static final String[] CLASS_NAMES = {JournalArticle.class.getName()};
084    
085            public static boolean JOURNAL_ARTICLE_INDEX_ALL_VERSIONS =
086                    GetterUtil.getBoolean(PropsUtil.get(
087                            "journal.articles.index.all.versions"));
088    
089            public static final String PORTLET_ID = PortletKeys.JOURNAL;
090    
091            public JournalArticleIndexer() {
092                    setFilterSearch(true);
093                    setPermissionAware(true);
094            }
095    
096            @Override
097            public String[] getClassNames() {
098                    return CLASS_NAMES;
099            }
100    
101            @Override
102            public String getPortletId() {
103                    return PORTLET_ID;
104            }
105    
106            @Override
107            public boolean hasPermission(
108                            PermissionChecker permissionChecker, String entryClassName,
109                            long entryClassPK, String actionId)
110                    throws Exception {
111    
112                    return JournalArticlePermission.contains(
113                            permissionChecker, entryClassPK, ActionKeys.VIEW);
114            }
115    
116            @Override
117            public boolean isVisible(long classPK, int status) throws Exception {
118                    List<JournalArticle> articles =
119                            JournalArticleLocalServiceUtil.getArticlesByResourcePrimKey(
120                                    classPK);
121    
122                    for (JournalArticle article : articles) {
123                            if (isVisible(article.getStatus(), status)) {
124                                    return true;
125                            }
126                    }
127    
128                    return false;
129            }
130    
131            @Override
132            public void postProcessContextQuery(
133                            BooleanQuery contextQuery, SearchContext searchContext)
134                    throws Exception {
135    
136                    Long classNameId = (Long)searchContext.getAttribute(
137                            Field.CLASS_NAME_ID);
138    
139                    if ((classNameId != null) && (classNameId.longValue() != 0)) {
140                            contextQuery.addRequiredTerm("classNameId", classNameId.toString());
141                    }
142    
143                    addStatus(contextQuery, searchContext);
144    
145                    addSearchClassTypeIds(contextQuery, searchContext);
146    
147                    String ddmStructureFieldName = (String)searchContext.getAttribute(
148                            "ddmStructureFieldName");
149                    Serializable ddmStructureFieldValue = searchContext.getAttribute(
150                            "ddmStructureFieldValue");
151    
152                    if (Validator.isNotNull(ddmStructureFieldName) &&
153                            Validator.isNotNull(ddmStructureFieldValue)) {
154    
155                            String[] ddmStructureFieldNameParts = StringUtil.split(
156                                    ddmStructureFieldName, StringPool.SLASH);
157    
158                            DDMStructure structure = DDMStructureLocalServiceUtil.getStructure(
159                                    GetterUtil.getLong(ddmStructureFieldNameParts[1]));
160    
161                            String fieldName = StringUtil.replaceLast(
162                                    ddmStructureFieldNameParts[2],
163                                    StringPool.UNDERLINE.concat(
164                                            LocaleUtil.toLanguageId(searchContext.getLocale())),
165                                    StringPool.BLANK);
166    
167                            try {
168                                    ddmStructureFieldValue = DDMUtil.getIndexedFieldValue(
169                                            ddmStructureFieldValue, structure.getFieldType(fieldName));
170                            }
171                            catch (StructureFieldException sfe) {
172                            }
173    
174                            contextQuery.addRequiredTerm(
175                                    ddmStructureFieldName,
176                                    StringPool.QUOTE + ddmStructureFieldValue + StringPool.QUOTE);
177                    }
178    
179                    String articleType = (String)searchContext.getAttribute("articleType");
180    
181                    if (Validator.isNotNull(articleType)) {
182                            contextQuery.addRequiredTerm(Field.TYPE, articleType);
183                    }
184    
185                    String ddmStructureKey = (String)searchContext.getAttribute(
186                            "ddmStructureKey");
187    
188                    if (Validator.isNotNull(ddmStructureKey)) {
189                            contextQuery.addRequiredTerm("ddmStructureKey", ddmStructureKey);
190                    }
191    
192                    String ddmTemplateKey = (String)searchContext.getAttribute(
193                            "ddmTemplateKey");
194    
195                    if (Validator.isNotNull(ddmTemplateKey)) {
196                            contextQuery.addRequiredTerm("ddmTemplateKey", ddmTemplateKey);
197                    }
198    
199                    boolean head = GetterUtil.getBoolean(
200                            searchContext.getAttribute("head"), Boolean.TRUE);
201                    boolean relatedClassName = GetterUtil.getBoolean(
202                            searchContext.getAttribute("relatedClassName"));
203    
204                    if (head && !relatedClassName) {
205                            contextQuery.addRequiredTerm("head", Boolean.TRUE);
206                    }
207            }
208    
209            @Override
210            public void postProcessSearchQuery(
211                            BooleanQuery searchQuery, SearchContext searchContext)
212                    throws Exception {
213    
214                    addSearchTerm(searchQuery, searchContext, Field.CLASS_PK, false);
215                    addSearchLocalizedTerm(
216                            searchQuery, searchContext, Field.CONTENT, false);
217                    addSearchLocalizedTerm(
218                            searchQuery, searchContext, Field.DESCRIPTION, false);
219                    addSearchTerm(searchQuery, searchContext, Field.ENTRY_CLASS_PK, false);
220                    addSearchLocalizedTerm(searchQuery, searchContext, Field.TITLE, false);
221                    addSearchTerm(searchQuery, searchContext, Field.TYPE, false);
222                    addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);
223    
224                    addSearchTerm(searchQuery, searchContext, "articleId", false);
225    
226                    LinkedHashMap<String, Object> params =
227                            (LinkedHashMap<String, Object>)searchContext.getAttribute("params");
228    
229                    if (params != null) {
230                            String expandoAttributes = (String)params.get("expandoAttributes");
231    
232                            if (Validator.isNotNull(expandoAttributes)) {
233                                    addSearchExpando(searchQuery, searchContext, expandoAttributes);
234                            }
235                    }
236            }
237    
238            protected void addDDMStructureAttributes(
239                            Document document, JournalArticle article)
240                    throws Exception {
241    
242                    if (Validator.isNull(article.getStructureId())) {
243                            return;
244                    }
245    
246                    DDMStructure ddmStructure = DDMStructureLocalServiceUtil.fetchStructure(
247                            article.getGroupId(),
248                            PortalUtil.getClassNameId(JournalArticle.class),
249                            article.getStructureId(), true);
250    
251                    if (ddmStructure == null) {
252                            return;
253                    }
254    
255                    document.addKeyword(Field.CLASS_TYPE_ID, ddmStructure.getStructureId());
256    
257                    Fields fields = null;
258    
259                    try {
260                            fields = JournalConverterUtil.getDDMFields(
261                                    ddmStructure, article.getContent());
262                    }
263                    catch (Exception e) {
264                            return;
265                    }
266    
267                    if (fields != null) {
268                            DDMIndexerUtil.addAttributes(document, ddmStructure, fields);
269                    }
270            }
271    
272            @Override
273            protected void addSearchLocalizedTerm(
274                            BooleanQuery searchQuery, SearchContext searchContext, String field,
275                            boolean like)
276                    throws Exception {
277    
278                    if (Validator.isNull(field)) {
279                            return;
280                    }
281    
282                    String value = String.valueOf(searchContext.getAttribute(field));
283    
284                    if (Validator.isNull(value)) {
285                            value = searchContext.getKeywords();
286                    }
287    
288                    if (Validator.isNull(value)) {
289                            return;
290                    }
291    
292                    String localizedField = DocumentImpl.getLocalizedName(
293                            searchContext.getLocale(), field);
294    
295                    if (Validator.isNull(searchContext.getKeywords())) {
296                            BooleanQuery localizedQuery = BooleanQueryFactoryUtil.create(
297                                    searchContext);
298    
299                            localizedQuery.addTerm(field, value, like);
300                            localizedQuery.addTerm(localizedField, value, like);
301    
302                            BooleanClauseOccur booleanClauseOccur = BooleanClauseOccur.SHOULD;
303    
304                            if (searchContext.isAndSearch()) {
305                                    booleanClauseOccur = BooleanClauseOccur.MUST;
306                            }
307    
308                            searchQuery.add(localizedQuery, booleanClauseOccur);
309                    }
310                    else {
311                            searchQuery.addTerm(localizedField, value, like);
312                    }
313            }
314    
315            @Override
316            protected void doDelete(Object obj) throws Exception {
317                    JournalArticle article = (JournalArticle)obj;
318    
319                    long classPK = article.getId();
320    
321                    if (!JOURNAL_ARTICLE_INDEX_ALL_VERSIONS) {
322                            classPK = article.getResourcePrimKey();
323                    }
324    
325                    deleteDocument(article.getCompanyId(), classPK);
326    
327                    if (!article.isApproved()) {
328                            return;
329                    }
330    
331                    JournalArticle latestIndexableArticle =
332                            JournalArticleLocalServiceUtil.fetchLatestIndexableArticle(
333                                    article.getResourcePrimKey());
334    
335                    if ((latestIndexableArticle == null) ||
336                            (JOURNAL_ARTICLE_INDEX_ALL_VERSIONS &&
337                            (latestIndexableArticle.getVersion() > article.getVersion()))) {
338    
339                            return;
340                    }
341    
342                    SearchEngineUtil.updateDocument(
343                            getSearchEngineId(), article.getCompanyId(),
344                            getDocument(latestIndexableArticle));
345            }
346    
347            @Override
348            protected Document doGetDocument(Object obj) throws Exception {
349                    JournalArticle article = (JournalArticle)obj;
350    
351                    Document document = getBaseModelDocument(PORTLET_ID, article);
352    
353                    long classPK = article.getId();
354    
355                    if (!JOURNAL_ARTICLE_INDEX_ALL_VERSIONS) {
356                            classPK = article.getResourcePrimKey();
357                    }
358    
359                    document.addUID(PORTLET_ID, classPK);
360    
361                    String articleDefaultLanguageId = LocalizationUtil.getDefaultLanguageId(
362                            article.getContent());
363    
364                    Locale defaultLocale = LocaleUtil.getSiteDefault();
365    
366                    String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
367    
368                    String[] languageIds = getLanguageIds(
369                            defaultLanguageId, article.getContent());
370    
371                    for (String languageId : languageIds) {
372                            String content = extractContent(article, languageId);
373    
374                            String description = article.getDescription(languageId);
375    
376                            String title = article.getTitle(languageId);
377    
378                            if (languageId.equals(articleDefaultLanguageId)) {
379                                    document.addText(Field.CONTENT, content);
380                                    document.addText(Field.DESCRIPTION, description);
381                                    document.addText(Field.TITLE, title);
382                                    document.addText("defaultLanguageId", languageId);
383                            }
384    
385                            document.addText(
386                                    Field.CONTENT.concat(StringPool.UNDERLINE).concat(languageId),
387                                    content);
388                            document.addText(
389                                    Field.DESCRIPTION.concat(StringPool.UNDERLINE).concat(
390                                            languageId), description);
391                            document.addText(
392                                    Field.TITLE.concat(StringPool.UNDERLINE).concat(languageId),
393                                    title);
394                    }
395    
396                    document.addKeyword(Field.FOLDER_ID, article.getFolderId());
397                    document.addKeyword(Field.LAYOUT_UUID, article.getLayoutUuid());
398                    document.addKeyword(
399                            Field.TREE_PATH,
400                            StringUtil.split(article.getTreePath(), CharPool.SLASH));
401                    document.addKeyword(Field.TYPE, article.getType());
402                    document.addKeyword(Field.VERSION, article.getVersion());
403    
404                    String articleId = article.getArticleId();
405    
406                    if (article.isInTrash()) {
407                            articleId = TrashUtil.getOriginalTitle(articleId);
408                    }
409    
410                    document.addKeyword("articleId", articleId);
411                    document.addKeyword("ddmStructureKey", article.getStructureId());
412                    document.addKeyword("ddmTemplateKey", article.getTemplateId());
413                    document.addDate("displayDate", article.getDisplayDate());
414                    document.addKeyword("head", isHead(article));
415    
416                    addDDMStructureAttributes(document, article);
417    
418                    return document;
419            }
420    
421            @Override
422            protected String doGetSortField(String orderByCol) {
423                    if (orderByCol.equals("display-date")) {
424                            return "displayDate";
425                    }
426                    else if (orderByCol.equals("id")) {
427                            return Field.ENTRY_CLASS_PK;
428                    }
429                    else if (orderByCol.equals("modified-date")) {
430                            return Field.MODIFIED_DATE;
431                    }
432                    else if (orderByCol.equals("title")) {
433                            return Field.TITLE;
434                    }
435                    else {
436                            return orderByCol;
437                    }
438            }
439    
440            @Override
441            protected Summary doGetSummary(
442                    Document document, Locale locale, String snippet,
443                    PortletURL portletURL) {
444    
445                    Locale snippetLocale = getSnippetLocale(document, locale);
446    
447                    if (snippetLocale == null) {
448                            snippetLocale = LocaleUtil.fromLanguageId(
449                                    document.get("defaultLanguageId"));
450                    }
451    
452                    String prefix = Field.SNIPPET + StringPool.UNDERLINE;
453    
454                    String title = document.get(
455                            snippetLocale, prefix + Field.TITLE, Field.TITLE);
456    
457                    String content = StringPool.BLANK;
458    
459                    String ddmStructureKey = document.get("ddmStructureKey");
460    
461                    if (Validator.isNotNull(ddmStructureKey)) {
462                            content = getDDMContentSummary(document, snippetLocale);
463                    }
464                    else {
465                            content = getBasicContentSummary(document, snippetLocale);
466                    }
467    
468                    String groupId = document.get(Field.GROUP_ID);
469                    String articleId = document.get("articleId");
470                    String version = document.get(Field.VERSION);
471    
472                    portletURL.setParameter("struts_action", "/journal/edit_article");
473                    portletURL.setParameter("groupId", groupId);
474                    portletURL.setParameter("articleId", articleId);
475                    portletURL.setParameter("version", version);
476    
477                    return new Summary(snippetLocale, title, content, portletURL);
478            }
479    
480            @Override
481            protected void doReindex(Object obj) throws Exception {
482                    JournalArticle article = (JournalArticle)obj;
483    
484                    if (PortalUtil.getClassNameId(DDMStructure.class) ==
485                                    article.getClassNameId()) {
486    
487                            Document document = getDocument(article);
488    
489                            SearchEngineUtil.deleteDocument(
490                                    getSearchEngineId(), article.getCompanyId(),
491                                    document.get(Field.UID));
492    
493                            return;
494                    }
495    
496                    reindexArticleVersions(article);
497            }
498    
499            @Override
500            protected void doReindex(String className, long classPK) throws Exception {
501                    JournalArticle article =
502                            JournalArticleLocalServiceUtil.fetchJournalArticle(classPK);
503    
504                    if (article == null) {
505                            article =
506                                    JournalArticleLocalServiceUtil.fetchLatestIndexableArticle(
507                                            classPK);
508                    }
509    
510                    if (article != null) {
511                            doReindex(article);
512                    }
513            }
514    
515            @Override
516            protected void doReindex(String[] ids) throws Exception {
517                    long companyId = GetterUtil.getLong(ids[0]);
518    
519                    reindexArticles(companyId);
520            }
521    
522            @Override
523            protected void doReindexDDMStructures(List<Long> ddmStructureIds)
524                    throws Exception {
525    
526                    String[] ddmStructureKeys = new String[ddmStructureIds.size()];
527    
528                    for (int i = 0; i < ddmStructureIds.size(); i++) {
529                            long structureId = ddmStructureIds.get(i);
530    
531                            DDMStructure ddmStructure =
532                                    DDMStructureLocalServiceUtil.getDDMStructure(structureId);
533    
534                            ddmStructureKeys[i] = ddmStructure.getStructureKey();
535                    }
536    
537                    List<JournalArticle> articles =
538                            JournalArticleLocalServiceUtil.getStructureArticles(
539                                    ddmStructureKeys);
540    
541                    for (JournalArticle article : articles) {
542                            doReindex(article);
543                    }
544            }
545    
546            protected String extractBasicContent(
547                    JournalArticle article, String languageId) {
548    
549                    String content = article.getContentByLocale(languageId);
550    
551                    content = StringUtil.replace(content, "<![CDATA[", StringPool.BLANK);
552                    content = StringUtil.replace(content, "]]>", StringPool.BLANK);
553                    content = StringUtil.replace(content, "&amp;", "&");
554                    content = StringUtil.replace(content, "&lt;", "<");
555                    content = StringUtil.replace(content, "&gt;", ">");
556    
557                    content = HtmlUtil.extractText(content);
558    
559                    return content;
560            }
561    
562            protected String extractContent(JournalArticle article, String languageId)
563                    throws Exception {
564    
565                    if (Validator.isNotNull(article.getStructureId())) {
566                            return extractDDMContent(article, languageId);
567                    }
568    
569                    return extractBasicContent(article, languageId);
570            }
571    
572            protected String extractDDMContent(
573                            JournalArticle article, String languageId)
574                    throws Exception {
575    
576                    if (Validator.isNull(article.getStructureId())) {
577                            return StringPool.BLANK;
578                    }
579    
580                    DDMStructure ddmStructure = DDMStructureLocalServiceUtil.fetchStructure(
581                            article.getGroupId(),
582                            PortalUtil.getClassNameId(JournalArticle.class),
583                            article.getStructureId(), true);
584    
585                    if (ddmStructure == null) {
586                            return StringPool.BLANK;
587                    }
588    
589                    Fields fields = null;
590    
591                    try {
592                            fields = JournalConverterUtil.getDDMFields(
593                                    ddmStructure, article.getContent());
594                    }
595                    catch (Exception e) {
596                            return StringPool.BLANK;
597                    }
598    
599                    if (fields == null) {
600                            return StringPool.BLANK;
601                    }
602    
603                    return DDMIndexerUtil.extractAttributes(
604                            ddmStructure, fields, LocaleUtil.fromLanguageId(languageId));
605            }
606    
607            protected Collection<Document> getArticleVersions(JournalArticle article)
608                    throws PortalException, SystemException {
609    
610                    Collection<Document> documents = new ArrayList<Document>();
611    
612                    List<JournalArticle> articles = null;
613    
614                    if (JOURNAL_ARTICLE_INDEX_ALL_VERSIONS) {
615                            articles =
616                                    JournalArticleLocalServiceUtil.
617                                            getIndexableArticlesByResourcePrimKey(
618                                                    article.getResourcePrimKey());
619                    }
620                    else {
621                            articles = new ArrayList<JournalArticle>();
622    
623                            JournalArticle latestIndexableArticle =
624                                    JournalArticleLocalServiceUtil.fetchLatestIndexableArticle(
625                                            article.getResourcePrimKey());
626    
627                            if (latestIndexableArticle != null) {
628                                    articles.add(latestIndexableArticle);
629                            }
630                    }
631    
632                    for (JournalArticle curArticle : articles) {
633                            Document document = getDocument(curArticle);
634    
635                            documents.add(document);
636                    }
637    
638                    return documents;
639            }
640    
641            protected String getBasicContentSummary(
642                    Document document, Locale snippetLocale) {
643    
644                    String prefix = Field.SNIPPET + StringPool.UNDERLINE;
645    
646                    String content = document.get(
647                            snippetLocale, prefix + Field.DESCRIPTION, prefix + Field.CONTENT);
648    
649                    if (Validator.isBlank(content)) {
650                            content = document.get(
651                                    snippetLocale, Field.DESCRIPTION, Field.CONTENT);
652                    }
653    
654                    if (content.length() > 200) {
655                            content = StringUtil.shorten(content, 200);
656                    }
657    
658                    return content;
659            }
660    
661            protected String getDDMContentSummary(
662                    Document document, Locale snippetLocale) {
663    
664                    String content = StringPool.BLANK;
665    
666                    try {
667                            long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
668                            String articleId = document.get("articleId");
669                            double version = GetterUtil.getDouble(document.get(Field.VERSION));
670    
671                            JournalArticle article =
672                                    JournalArticleLocalServiceUtil.fetchArticle(
673                                            groupId, articleId, version);
674    
675                            if (article == null) {
676                                    return content;
677                            }
678    
679                            JournalArticleDisplay articleDisplay =
680                                    JournalArticleLocalServiceUtil.getArticleDisplay(
681                                            article, null, Constants.VIEW,
682                                            LocaleUtil.toLanguageId(snippetLocale), 1, null, null);
683    
684                            content = HtmlUtil.escape(articleDisplay.getDescription());
685                            content = HtmlUtil.replaceNewLine(content);
686    
687                            if (Validator.isNull(content)) {
688                                    content = HtmlUtil.extractText(articleDisplay.getContent());
689                            }
690                    }
691                    catch (Exception e) {
692                            if (_log.isDebugEnabled()) {
693                                    _log.debug(e, e);
694                            }
695                    }
696    
697                    return content;
698            }
699    
700            protected String[] getLanguageIds(
701                    String defaultLanguageId, String content) {
702    
703                    String[] languageIds = LocalizationUtil.getAvailableLanguageIds(
704                            content);
705    
706                    if (languageIds.length == 0) {
707                            languageIds = new String[] {defaultLanguageId};
708                    }
709    
710                    return languageIds;
711            }
712    
713            protected boolean isHead(JournalArticle article) throws SystemException {
714                    if (!JOURNAL_ARTICLE_INDEX_ALL_VERSIONS) {
715                            return true;
716                    }
717    
718                    JournalArticle latestArticle =
719                            JournalArticleLocalServiceUtil.fetchLatestArticle(
720                                    article.getResourcePrimKey(),
721                                    new int[] {
722                                            WorkflowConstants.STATUS_APPROVED,
723                                            WorkflowConstants.STATUS_IN_TRASH});
724    
725                    if ((latestArticle != null) && !latestArticle.isIndexable()) {
726                            return false;
727                    }
728                    else if ((latestArticle != null) &&
729                                     (article.getId() == latestArticle.getId())) {
730    
731                            return true;
732                    }
733    
734                    return false;
735            }
736    
737            @Override
738            protected String getPortletId(SearchContext searchContext) {
739                    return PORTLET_ID;
740            }
741    
742            protected void reindexArticles(long companyId)
743                    throws PortalException, SystemException {
744    
745                    ActionableDynamicQuery actionableDynamicQuery =
746                            new JournalArticleActionableDynamicQuery() {
747    
748                            @Override
749                            protected void addCriteria(DynamicQuery dynamicQuery) {
750                                    if (JOURNAL_ARTICLE_INDEX_ALL_VERSIONS) {
751                                            return;
752                                    }
753    
754                                    Property statusProperty = PropertyFactoryUtil.forName("status");
755    
756                                    Integer[] statuses = {
757                                            WorkflowConstants.STATUS_APPROVED,
758                                            WorkflowConstants.STATUS_IN_TRASH
759                                    };
760    
761                                    dynamicQuery.add(statusProperty.in(statuses));
762                            }
763    
764                            @Override
765                            protected void performAction(Object object) throws PortalException {
766                                    JournalArticle article = (JournalArticle)object;
767    
768                                    Document document = getDocument(article);
769    
770                                    addDocument(document);
771                            }
772    
773                    };
774    
775                    actionableDynamicQuery.setCompanyId(companyId);
776                    actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
777    
778                    actionableDynamicQuery.performActions();
779            }
780    
781            protected void reindexArticleVersions(JournalArticle article)
782                    throws PortalException, SystemException {
783    
784                    SearchEngineUtil.updateDocuments(
785                            getSearchEngineId(), article.getCompanyId(),
786                            getArticleVersions(article));
787            }
788    
789            private static Log _log = LogFactoryUtil.getLog(
790                    JournalArticleIndexer.class);
791    
792    }