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