001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.journal.service.impl;
016    
017    import com.liferay.portal.LocaleException;
018    import com.liferay.portal.NoSuchImageException;
019    import com.liferay.portal.kernel.dao.orm.QueryUtil;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.exception.SystemException;
022    import com.liferay.portal.kernel.language.LanguageUtil;
023    import com.liferay.portal.kernel.lar.ImportExportThreadLocal;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
027    import com.liferay.portal.kernel.search.Field;
028    import com.liferay.portal.kernel.search.Hits;
029    import com.liferay.portal.kernel.search.Indexer;
030    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
031    import com.liferay.portal.kernel.search.QueryConfig;
032    import com.liferay.portal.kernel.search.SearchContext;
033    import com.liferay.portal.kernel.search.Sort;
034    import com.liferay.portal.kernel.util.ArrayUtil;
035    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
036    import com.liferay.portal.kernel.util.CharPool;
037    import com.liferay.portal.kernel.util.ContentTypes;
038    import com.liferay.portal.kernel.util.FileUtil;
039    import com.liferay.portal.kernel.util.GetterUtil;
040    import com.liferay.portal.kernel.util.HtmlUtil;
041    import com.liferay.portal.kernel.util.HttpUtil;
042    import com.liferay.portal.kernel.util.ListUtil;
043    import com.liferay.portal.kernel.util.LocaleUtil;
044    import com.liferay.portal.kernel.util.LocalizationUtil;
045    import com.liferay.portal.kernel.util.MathUtil;
046    import com.liferay.portal.kernel.util.OrderByComparator;
047    import com.liferay.portal.kernel.util.ParamUtil;
048    import com.liferay.portal.kernel.util.PropsKeys;
049    import com.liferay.portal.kernel.util.StringPool;
050    import com.liferay.portal.kernel.util.StringUtil;
051    import com.liferay.portal.kernel.util.Time;
052    import com.liferay.portal.kernel.util.Validator;
053    import com.liferay.portal.kernel.workflow.WorkflowConstants;
054    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
055    import com.liferay.portal.kernel.xml.Document;
056    import com.liferay.portal.kernel.xml.DocumentException;
057    import com.liferay.portal.kernel.xml.Element;
058    import com.liferay.portal.kernel.xml.Node;
059    import com.liferay.portal.kernel.xml.SAXReaderUtil;
060    import com.liferay.portal.kernel.xml.XPath;
061    import com.liferay.portal.model.Company;
062    import com.liferay.portal.model.Group;
063    import com.liferay.portal.model.Image;
064    import com.liferay.portal.model.ResourceConstants;
065    import com.liferay.portal.model.User;
066    import com.liferay.portal.service.ServiceContext;
067    import com.liferay.portal.service.ServiceContextUtil;
068    import com.liferay.portal.servlet.filters.cache.CacheUtil;
069    import com.liferay.portal.theme.ThemeDisplay;
070    import com.liferay.portal.util.PortalUtil;
071    import com.liferay.portal.util.PortletKeys;
072    import com.liferay.portal.util.PrefsPropsUtil;
073    import com.liferay.portal.util.PropsValues;
074    import com.liferay.portal.util.SubscriptionSender;
075    import com.liferay.portal.webserver.WebServerServletTokenUtil;
076    import com.liferay.portlet.asset.NoSuchEntryException;
077    import com.liferay.portlet.asset.model.AssetEntry;
078    import com.liferay.portlet.asset.model.AssetLink;
079    import com.liferay.portlet.asset.model.AssetLinkConstants;
080    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
081    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
082    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
083    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
084    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
085    import com.liferay.portlet.expando.model.ExpandoBridge;
086    import com.liferay.portlet.journal.ArticleContentException;
087    import com.liferay.portlet.journal.ArticleDisplayDateException;
088    import com.liferay.portlet.journal.ArticleExpirationDateException;
089    import com.liferay.portlet.journal.ArticleIdException;
090    import com.liferay.portlet.journal.ArticleReviewDateException;
091    import com.liferay.portlet.journal.ArticleSmallImageNameException;
092    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
093    import com.liferay.portlet.journal.ArticleTitleException;
094    import com.liferay.portlet.journal.ArticleTypeException;
095    import com.liferay.portlet.journal.ArticleVersionException;
096    import com.liferay.portlet.journal.DuplicateArticleIdException;
097    import com.liferay.portlet.journal.NoSuchArticleException;
098    import com.liferay.portlet.journal.NoSuchArticleResourceException;
099    import com.liferay.portlet.journal.StructureXsdException;
100    import com.liferay.portlet.journal.model.JournalArticle;
101    import com.liferay.portlet.journal.model.JournalArticleConstants;
102    import com.liferay.portlet.journal.model.JournalArticleDisplay;
103    import com.liferay.portlet.journal.model.JournalArticleResource;
104    import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
105    import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
106    import com.liferay.portlet.journal.util.JournalUtil;
107    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
108    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
109    import com.liferay.portlet.journalcontent.util.JournalContentUtil;
110    
111    import java.io.File;
112    import java.io.IOException;
113    import java.io.Serializable;
114    
115    import java.util.Calendar;
116    import java.util.Date;
117    import java.util.HashMap;
118    import java.util.HashSet;
119    import java.util.LinkedHashMap;
120    import java.util.List;
121    import java.util.Locale;
122    import java.util.Map;
123    import java.util.Set;
124    
125    import javax.portlet.PortletPreferences;
126    
127    /**
128     * @author Brian Wing Shun Chan
129     * @author Raymond Augé
130     * @author Bruno Farache
131     * @author Juan Fernández
132     */
133    public class JournalArticleLocalServiceImpl
134            extends JournalArticleLocalServiceBaseImpl {
135    
136            public JournalArticle addArticle(
137                            long userId, long groupId, long folderId, long classNameId,
138                            long classPK, String articleId, boolean autoArticleId,
139                            double version, Map<Locale, String> titleMap,
140                            Map<Locale, String> descriptionMap, String content, String type,
141                            String structureId, String templateId, String layoutUuid,
142                            int displayDateMonth, int displayDateDay, int displayDateYear,
143                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
144                            int expirationDateDay, int expirationDateYear,
145                            int expirationDateHour, int expirationDateMinute,
146                            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
147                            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
148                            boolean neverReview, boolean indexable, boolean smallImage,
149                            String smallImageURL, File smallImageFile,
150                            Map<String, byte[]> images, String articleURL,
151                            ServiceContext serviceContext)
152                    throws PortalException, SystemException {
153    
154                    // Article
155    
156                    User user = userPersistence.findByPrimaryKey(userId);
157                    articleId = articleId.trim().toUpperCase();
158    
159                    Date displayDate = null;
160                    Date expirationDate = null;
161                    Date reviewDate = null;
162    
163                    if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
164                            displayDate = PortalUtil.getDate(
165                                    displayDateMonth, displayDateDay, displayDateYear,
166                                    displayDateHour, displayDateMinute, user.getTimeZone(),
167                                    ArticleDisplayDateException.class);
168    
169                            if (!neverExpire) {
170                                    expirationDate = PortalUtil.getDate(
171                                            expirationDateMonth, expirationDateDay, expirationDateYear,
172                                            expirationDateHour, expirationDateMinute,
173                                            user.getTimeZone(), ArticleExpirationDateException.class);
174                            }
175    
176                            if (!neverReview) {
177                                    reviewDate = PortalUtil.getDate(
178                                            reviewDateMonth, reviewDateDay, reviewDateYear,
179                                            reviewDateHour, reviewDateMinute, user.getTimeZone(),
180                                            ArticleReviewDateException.class);
181                            }
182                    }
183    
184                    byte[] smallImageBytes = null;
185    
186                    try {
187                            smallImageBytes = FileUtil.getBytes(smallImageFile);
188                    }
189                    catch (IOException ioe) {
190                    }
191    
192                    Date now = new Date();
193    
194                    validate(
195                            user.getCompanyId(), groupId, classNameId, articleId, autoArticleId,
196                            version, titleMap, content, type, structureId, templateId,
197                            expirationDate, smallImage, smallImageURL, smallImageFile,
198                            smallImageBytes);
199    
200                    if (autoArticleId) {
201                            articleId = String.valueOf(counterLocalService.increment());
202                    }
203    
204                    long id = counterLocalService.increment();
205    
206                    long resourcePrimKey =
207                            journalArticleResourceLocalService.getArticleResourcePrimKey(
208                                    serviceContext.getUuid(), groupId, articleId);
209    
210                    JournalArticle article = journalArticlePersistence.create(id);
211    
212                    Locale locale = LocaleUtil.getDefault();
213    
214                    String defaultLanguageId = ParamUtil.getString(
215                            serviceContext, "defaultLanguageId");
216    
217                    if (Validator.isNull(defaultLanguageId)) {
218                            defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
219                    }
220    
221                    if (Validator.isNotNull(defaultLanguageId)) {
222                            locale = LocaleUtil.fromLanguageId(defaultLanguageId);
223                    }
224    
225                    String title = titleMap.get(locale);
226    
227                    content = format(
228                            user, groupId, articleId, version, false, content, structureId,
229                            images);
230    
231                    article.setResourcePrimKey(resourcePrimKey);
232                    article.setGroupId(groupId);
233                    article.setCompanyId(user.getCompanyId());
234                    article.setUserId(user.getUserId());
235                    article.setUserName(user.getFullName());
236                    article.setCreateDate(serviceContext.getCreateDate(now));
237                    article.setModifiedDate(serviceContext.getModifiedDate(now));
238                    article.setFolderId(folderId);
239                    article.setClassNameId(classNameId);
240                    article.setClassPK(classPK);
241                    article.setArticleId(articleId);
242                    article.setVersion(version);
243                    article.setTitleMap(titleMap, locale);
244                    article.setUrlTitle(
245                            getUniqueUrlTitle(id, articleId, title, null, serviceContext));
246                    article.setDescriptionMap(descriptionMap, locale);
247                    article.setContent(content);
248                    article.setType(type);
249                    article.setStructureId(structureId);
250                    article.setTemplateId(templateId);
251                    article.setLayoutUuid(layoutUuid);
252                    article.setDisplayDate(displayDate);
253                    article.setExpirationDate(expirationDate);
254                    article.setReviewDate(reviewDate);
255                    article.setIndexable(indexable);
256                    article.setSmallImage(smallImage);
257                    article.setSmallImageId(counterLocalService.increment());
258                    article.setSmallImageURL(smallImageURL);
259    
260                    if ((expirationDate == null) || expirationDate.after(now)) {
261                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
262                    }
263                    else {
264                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
265                    }
266    
267                    journalArticlePersistence.update(article);
268    
269                    // Resources
270    
271                    if (serviceContext.isAddGroupPermissions() ||
272                            serviceContext.isAddGuestPermissions()) {
273    
274                            addArticleResources(
275                                    article, serviceContext.isAddGroupPermissions(),
276                                    serviceContext.isAddGuestPermissions());
277                    }
278                    else {
279                            addArticleResources(
280                                    article, serviceContext.getGroupPermissions(),
281                                    serviceContext.getGuestPermissions());
282                    }
283    
284                    // Expando
285    
286                    ExpandoBridge expandoBridge = article.getExpandoBridge();
287    
288                    expandoBridge.setAttributes(serviceContext);
289    
290                    // Small image
291    
292                    saveImages(
293                            smallImage, article.getSmallImageId(), smallImageFile,
294                            smallImageBytes);
295    
296                    // Asset
297    
298                    updateAsset(
299                            userId, article, serviceContext.getAssetCategoryIds(),
300                            serviceContext.getAssetTagNames(),
301                            serviceContext.getAssetLinkEntryIds());
302    
303                    // Message boards
304    
305                    if (PropsValues.JOURNAL_ARTICLE_COMMENTS_ENABLED) {
306                            mbMessageLocalService.addDiscussionMessage(
307                                    userId, article.getUserName(), groupId,
308                                    JournalArticle.class.getName(), resourcePrimKey,
309                                    WorkflowConstants.ACTION_PUBLISH);
310                    }
311    
312                    // Email
313    
314                    PortletPreferences preferences =
315                            ServiceContextUtil.getPortletPreferences(serviceContext);
316    
317                    sendEmail(
318                            article, articleURL, preferences, "requested", serviceContext);
319    
320                    // Workflow
321    
322                    if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
323                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
324                                    user.getCompanyId(), groupId, userId,
325                                    JournalArticle.class.getName(), article.getId(), article,
326                                    serviceContext);
327    
328                            if (serviceContext.getWorkflowAction() !=
329                                            WorkflowConstants.ACTION_PUBLISH) {
330    
331                                    // Indexer
332    
333                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
334                                            JournalArticle.class);
335    
336                                    indexer.reindex(article);
337                            }
338                    }
339                    else {
340                            updateStatus(
341                                    userId, article, WorkflowConstants.STATUS_APPROVED, null,
342                                    serviceContext);
343                    }
344    
345                    return article;
346            }
347    
348            public JournalArticle addArticle(
349                            long userId, long groupId, long folderId,
350                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
351                            String content, String structureId, String templateId,
352                            ServiceContext serviceContext)
353                    throws PortalException, SystemException {
354    
355                    Calendar calendar = CalendarFactoryUtil.getCalendar();
356    
357                    int displayDateMonth = calendar.get(Calendar.MONTH);
358                    int displayDateDay = calendar.get(Calendar.DAY_OF_MONTH);
359                    int displayDateYear = calendar.get(Calendar.YEAR);
360                    int displayDateHour = calendar.get(Calendar.HOUR_OF_DAY);
361                    int displayDateMinute = calendar.get(Calendar.MINUTE);
362    
363                    return addArticle(
364                            userId, groupId, folderId,
365                            JournalArticleConstants.CLASSNAME_ID_DEFAULT, 0, StringPool.BLANK,
366                            true, 1, titleMap, descriptionMap, content, "general", structureId,
367                            templateId, null, displayDateMonth, displayDateDay, displayDateYear,
368                            displayDateHour, displayDateMinute, 0, 0, 0, 0, 0, true, 0, 0, 0, 0,
369                            0, true, true, false, null, null, null, null, serviceContext);
370            }
371    
372            public void addArticleResources(
373                            JournalArticle article, boolean addGroupPermissions,
374                            boolean addGuestPermissions)
375                    throws PortalException, SystemException {
376    
377                    resourceLocalService.addResources(
378                            article.getCompanyId(), article.getGroupId(), article.getUserId(),
379                            JournalArticle.class.getName(), article.getResourcePrimKey(), false,
380                            addGroupPermissions, addGuestPermissions);
381            }
382    
383            public void addArticleResources(
384                            JournalArticle article, String[] groupPermissions,
385                            String[] guestPermissions)
386                    throws PortalException, SystemException {
387    
388                    resourceLocalService.addModelResources(
389                            article.getCompanyId(), article.getGroupId(), article.getUserId(),
390                            JournalArticle.class.getName(), article.getResourcePrimKey(),
391                            groupPermissions, guestPermissions);
392            }
393    
394            public void addArticleResources(
395                            long groupId, String articleId, boolean addGroupPermissions,
396                            boolean addGuestPermissions)
397                    throws PortalException, SystemException {
398    
399                    JournalArticle article = getLatestArticle(groupId, articleId);
400    
401                    addArticleResources(article, addGroupPermissions, addGuestPermissions);
402            }
403    
404            public void addArticleResources(
405                            long groupId, String articleId, String[] groupPermissions,
406                            String[] guestPermissions)
407                    throws PortalException, SystemException {
408    
409                    JournalArticle article = getLatestArticle(groupId, articleId);
410    
411                    addArticleResources(article, groupPermissions, guestPermissions);
412            }
413    
414            public JournalArticle checkArticleResourcePrimKey(
415                            long groupId, String articleId, double version)
416                    throws PortalException, SystemException {
417    
418                    JournalArticle article = journalArticlePersistence.findByG_A_V(
419                            groupId, articleId, version);
420    
421                    if (article.getResourcePrimKey() > 0) {
422                            return article;
423                    }
424    
425                    long resourcePrimKey =
426                            journalArticleResourceLocalService.getArticleResourcePrimKey(
427                                    groupId, articleId);
428    
429                    article.setResourcePrimKey(resourcePrimKey);
430    
431                    journalArticlePersistence.update(article);
432    
433                    return article;
434            }
435    
436            public void checkArticles() throws PortalException, SystemException {
437                    Date now = new Date();
438    
439                    List<JournalArticle> articles =
440                            journalArticleFinder.findByExpirationDate(
441                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT,
442                                    WorkflowConstants.STATUS_APPROVED,
443                                    new Date(now.getTime() + _JOURNAL_ARTICLE_CHECK_INTERVAL));
444    
445                    if (_log.isDebugEnabled()) {
446                            _log.debug("Expiring " + articles.size() + " articles");
447                    }
448    
449                    Set<Long> companyIds = new HashSet<Long>();
450    
451                    for (JournalArticle article : articles) {
452                            if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
453                                    List<JournalArticle> currentArticles =
454                                            journalArticlePersistence.findByG_A(
455                                                    article.getGroupId(), article.getArticleId(),
456                                                    QueryUtil.ALL_POS, QueryUtil.ALL_POS,
457                                                    new ArticleVersionComparator(true));
458    
459                                    for (JournalArticle currentArticle : currentArticles) {
460                                            currentArticle.setExpirationDate(
461                                                    article.getExpirationDate());
462                                            currentArticle.setStatus(WorkflowConstants.STATUS_EXPIRED);
463    
464                                            journalArticlePersistence.update(currentArticle);
465                                    }
466                            }
467                            else {
468                                    article.setStatus(WorkflowConstants.STATUS_EXPIRED);
469    
470                                    journalArticlePersistence.update(article);
471                            }
472    
473                            updatePreviousApprovedArticle(article);
474    
475                            JournalContentUtil.clearCache(
476                                    article.getGroupId(), article.getArticleId(),
477                                    article.getTemplateId());
478    
479                            companyIds.add(article.getCompanyId());
480                    }
481    
482                    for (long companyId : companyIds) {
483                            CacheUtil.clearCache(companyId);
484                    }
485    
486                    if (_previousCheckDate == null) {
487                            _previousCheckDate = new Date(
488                                    now.getTime() - _JOURNAL_ARTICLE_CHECK_INTERVAL);
489                    }
490    
491                    articles = journalArticleFinder.findByReviewDate(
492                            JournalArticleConstants.CLASSNAME_ID_DEFAULT, now,
493                            _previousCheckDate);
494    
495                    if (_log.isDebugEnabled()) {
496                            _log.debug(
497                                    "Sending review notifications for " + articles.size() +
498                                            " articles");
499                    }
500    
501                    for (JournalArticle article : articles) {
502                            String articleURL = StringPool.BLANK;
503    
504                            long ownerId = article.getGroupId();
505                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
506                            long plid = PortletKeys.PREFS_PLID_SHARED;
507                            String portletId = PortletKeys.JOURNAL;
508    
509                            PortletPreferences preferences =
510                                    portletPreferencesLocalService.getPreferences(
511                                            article.getCompanyId(), ownerId, ownerType, plid,
512                                            portletId);
513    
514                            sendEmail(
515                                    article, articleURL, preferences, "review",
516                                    new ServiceContext());
517                    }
518    
519                    _previousCheckDate = now;
520            }
521    
522            public void checkNewLine(long groupId, String articleId, double version)
523                    throws PortalException, SystemException {
524    
525                    JournalArticle article = journalArticlePersistence.findByG_A_V(
526                            groupId, articleId, version);
527    
528                    String content = GetterUtil.getString(article.getContent());
529    
530                    if (content.contains("\\n")) {
531                            content = StringUtil.replace(
532                                    content, new String[] {"\\n", "\\r"},
533                                    new String[] {"\n", "\r"});
534    
535                            article.setContent(content);
536    
537                            journalArticlePersistence.update(article);
538                    }
539            }
540    
541            public void checkStructure(long groupId, String articleId, double version)
542                    throws PortalException, SystemException {
543    
544                    JournalArticle article = journalArticlePersistence.findByG_A_V(
545                            groupId, articleId, version);
546    
547                    if (Validator.isNull(article.getStructureId())) {
548                            return;
549                    }
550    
551                    checkStructure(article);
552            }
553    
554            public JournalArticle copyArticle(
555                            long userId, long groupId, String oldArticleId, String newArticleId,
556                            boolean autoArticleId, double version)
557                    throws PortalException, SystemException {
558    
559                    // Article
560    
561                    User user = userPersistence.findByPrimaryKey(userId);
562                    oldArticleId = oldArticleId.trim().toUpperCase();
563                    newArticleId = newArticleId.trim().toUpperCase();
564                    Date now = new Date();
565    
566                    JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
567                            groupId, oldArticleId, version);
568    
569                    if (autoArticleId) {
570                            newArticleId = String.valueOf(counterLocalService.increment());
571                    }
572                    else {
573                            validate(newArticleId);
574    
575                            if (journalArticlePersistence.countByG_A(
576                                            groupId, newArticleId) > 0) {
577    
578                                    throw new DuplicateArticleIdException();
579                            }
580                    }
581    
582                    long id = counterLocalService.increment();
583    
584                    long resourcePrimKey =
585                            journalArticleResourceLocalService.getArticleResourcePrimKey(
586                                    groupId, newArticleId);
587    
588                    JournalArticle newArticle = journalArticlePersistence.create(id);
589    
590                    newArticle.setResourcePrimKey(resourcePrimKey);
591                    newArticle.setGroupId(groupId);
592                    newArticle.setCompanyId(user.getCompanyId());
593                    newArticle.setUserId(user.getUserId());
594                    newArticle.setUserName(user.getFullName());
595                    newArticle.setCreateDate(now);
596                    newArticle.setModifiedDate(now);
597                    newArticle.setArticleId(newArticleId);
598                    newArticle.setVersion(JournalArticleConstants.VERSION_DEFAULT);
599                    newArticle.setTitle(oldArticle.getTitle());
600                    newArticle.setDescription(oldArticle.getDescription());
601    
602                    try {
603                            copyArticleImages(oldArticle, newArticle);
604                    }
605                    catch (Exception e) {
606                            newArticle.setContent(oldArticle.getContent());
607                    }
608    
609                    newArticle.setType(oldArticle.getType());
610                    newArticle.setStructureId(oldArticle.getStructureId());
611                    newArticle.setTemplateId(oldArticle.getTemplateId());
612                    newArticle.setLayoutUuid(oldArticle.getLayoutUuid());
613                    newArticle.setDisplayDate(oldArticle.getDisplayDate());
614                    newArticle.setExpirationDate(oldArticle.getExpirationDate());
615                    newArticle.setReviewDate(oldArticle.getReviewDate());
616                    newArticle.setIndexable(oldArticle.isIndexable());
617                    newArticle.setSmallImage(oldArticle.isSmallImage());
618                    newArticle.setSmallImageId(counterLocalService.increment());
619                    newArticle.setSmallImageURL(oldArticle.getSmallImageURL());
620                    newArticle.setStatus(oldArticle.getStatus());
621    
622                    journalArticlePersistence.update(newArticle);
623    
624                    // Resources
625    
626                    addArticleResources(newArticle, true, true);
627    
628                    // Small image
629    
630                    if (oldArticle.getSmallImage()) {
631                            Image image = imageLocalService.getImage(
632                                    oldArticle.getSmallImageId());
633    
634                            byte[] smallImageBytes = image.getTextObj();
635    
636                            imageLocalService.updateImage(
637                                    newArticle.getSmallImageId(), smallImageBytes);
638                    }
639    
640                    // Asset
641    
642                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
643                            JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
644                    String[] assetTagNames = assetTagLocalService.getTagNames(
645                            JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
646    
647                    updateAsset(userId, newArticle, assetCategoryIds, assetTagNames, null);
648    
649                    return newArticle;
650            }
651    
652            public void deleteArticle(JournalArticle article)
653                    throws PortalException, SystemException {
654    
655                    deleteArticle(article, StringPool.BLANK, null);
656            }
657    
658            public void deleteArticle(
659                            JournalArticle article, String articleURL,
660                            ServiceContext serviceContext)
661                    throws PortalException, SystemException {
662    
663                    if (article.isApproved() &&
664                            isLatestVersion(
665                                    article.getGroupId(), article.getArticleId(),
666                                    article.getVersion(), WorkflowConstants.STATUS_APPROVED)) {
667    
668                            updatePreviousApprovedArticle(article);
669                    }
670    
671                    // Email
672    
673                    if ((serviceContext != null) && Validator.isNotNull(articleURL)) {
674                            PortletPreferences preferences =
675                                    ServiceContextUtil.getPortletPreferences(serviceContext);
676    
677                            if ((preferences != null) && !article.isApproved() &&
678                                    isLatestVersion(
679                                            article.getGroupId(), article.getArticleId(),
680                                            article.getVersion())) {
681    
682                                    sendEmail(
683                                            article, articleURL, preferences, "denied", serviceContext);
684                            }
685                    }
686    
687                    // Images
688    
689                    journalArticleImageLocalService.deleteImages(
690                            article.getGroupId(), article.getArticleId(), article.getVersion());
691    
692                    // Workflow
693    
694                    if (!article.isDraft()) {
695                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
696                                    article.getCompanyId(), article.getGroupId(),
697                                    JournalArticle.class.getName(), article.getId());
698                    }
699    
700                    int articlesCount = journalArticlePersistence.countByG_A(
701                            article.getGroupId(), article.getArticleId());
702    
703                    if (articlesCount == 1) {
704    
705                            // Subscriptions
706    
707                            subscriptionLocalService.deleteSubscriptions(
708                                    article.getCompanyId(), JournalArticle.class.getName(),
709                                    article.getResourcePrimKey());
710    
711                            // Ratings
712    
713                            ratingsStatsLocalService.deleteStats(
714                                    JournalArticle.class.getName(), article.getResourcePrimKey());
715    
716                            // Message boards
717    
718                            mbMessageLocalService.deleteDiscussionMessages(
719                                    JournalArticle.class.getName(), article.getResourcePrimKey());
720    
721                            // Asset
722    
723                            assetEntryLocalService.deleteEntry(
724                                    JournalArticle.class.getName(), article.getResourcePrimKey());
725    
726                            // Content searches
727    
728                            journalContentSearchLocalService.deleteArticleContentSearches(
729                                    article.getGroupId(), article.getArticleId());
730    
731                            // Small image
732    
733                            imageLocalService.deleteImage(article.getSmallImageId());
734    
735                            // Expando
736    
737                            expandoValueLocalService.deleteValues(
738                                    JournalArticle.class.getName(), article.getId());
739    
740                            // Resources
741    
742                            resourceLocalService.deleteResource(
743                                    article.getCompanyId(), JournalArticle.class.getName(),
744                                    ResourceConstants.SCOPE_INDIVIDUAL,
745                                    article.getResourcePrimKey());
746    
747                            // Resource
748    
749                            try {
750                                    journalArticleResourceLocalService.deleteArticleResource(
751                                            article.getGroupId(), article.getArticleId());
752                            }
753                            catch (NoSuchArticleResourceException nsare) {
754                            }
755                    }
756    
757                    // Article
758    
759                    journalArticlePersistence.remove(article);
760            }
761    
762            public void deleteArticle(
763                            long groupId, String articleId, double version, String articleURL,
764                            ServiceContext serviceContext)
765                    throws PortalException, SystemException {
766    
767                    JournalArticle article = journalArticlePersistence.findByG_A_V(
768                            groupId, articleId, version);
769    
770                    deleteArticle(article, articleURL, serviceContext);
771            }
772    
773            public void deleteArticle(
774                            long groupId, String articleId, ServiceContext serviceContext)
775                    throws PortalException, SystemException {
776    
777                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
778                            groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
779                            new ArticleVersionComparator(true));
780    
781                    for (JournalArticle article : articles) {
782                            deleteArticle(article, null, serviceContext);
783                    }
784            }
785    
786            public void deleteArticles(long groupId)
787                    throws PortalException, SystemException {
788    
789                    for (JournalArticle article :
790                                    journalArticlePersistence.findByGroupId(groupId)) {
791    
792                            deleteArticle(article, null, null);
793                    }
794            }
795    
796            public void deleteArticles(long groupId, long folderId)
797                    throws PortalException, SystemException {
798    
799                    for (JournalArticle article :
800                                    journalArticlePersistence.findByG_F(groupId, folderId)) {
801    
802                            deleteArticle(article, null, null);
803                    }
804            }
805    
806            public void deleteLayoutArticleReferences(long groupId, String layoutUuid)
807                    throws SystemException {
808    
809                    List<JournalArticle> articles = journalArticlePersistence.findByG_L(
810                            groupId, layoutUuid);
811    
812                    for (JournalArticle article : articles) {
813                            article.setLayoutUuid(StringPool.BLANK);
814    
815                            journalArticlePersistence.update(article);
816                    }
817            }
818    
819            public JournalArticle expireArticle(
820                            long userId, long groupId, String articleId, double version,
821                            String articleURL, ServiceContext serviceContext)
822                    throws PortalException, SystemException {
823    
824                    return updateStatus(
825                            userId, groupId, articleId, version,
826                            WorkflowConstants.STATUS_EXPIRED, articleURL, serviceContext);
827            }
828    
829            public void expireArticle(
830                            long userId, long groupId, String articleId, String articleURL,
831                            ServiceContext serviceContext)
832                    throws PortalException, SystemException {
833    
834                    if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
835                            List<JournalArticle> articles = journalArticlePersistence.findByG_A(
836                                    groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
837                                    new ArticleVersionComparator(true));
838    
839                            for (JournalArticle article : articles) {
840                                    expireArticle(
841                                            userId, groupId, article.getArticleId(),
842                                            article.getVersion(), articleURL, serviceContext);
843                            }
844                    }
845                    else {
846                            JournalArticle article = getLatestArticle(
847                                    groupId, articleId, WorkflowConstants.STATUS_APPROVED);
848    
849                            expireArticle(
850                                    userId, groupId, article.getArticleId(), article.getVersion(),
851                                    articleURL, serviceContext);
852                    }
853            }
854    
855            public JournalArticle getArticle(long id)
856                    throws PortalException, SystemException {
857    
858                    return journalArticlePersistence.findByPrimaryKey(id);
859            }
860    
861            public JournalArticle getArticle(long groupId, String articleId)
862                    throws PortalException, SystemException {
863    
864                    // Get the latest article that is approved, if none are approved, get
865                    // the latest unapproved article
866    
867                    try {
868                            return getLatestArticle(
869                                    groupId, articleId, WorkflowConstants.STATUS_APPROVED);
870                    }
871                    catch (NoSuchArticleException nsae) {
872                            return getLatestArticle(
873                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
874                    }
875            }
876    
877            public JournalArticle getArticle(
878                            long groupId, String articleId, double version)
879                    throws PortalException, SystemException {
880    
881                    return journalArticlePersistence.findByG_A_V(
882                            groupId, articleId, version);
883            }
884    
885            public JournalArticle getArticle(
886                            long groupId, String className, long classPK)
887                    throws PortalException, SystemException {
888    
889                    long classNameId = PortalUtil.getClassNameId(className);
890    
891                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
892                            groupId, classNameId, classPK);
893    
894                    if (articles.isEmpty()) {
895                            throw new NoSuchArticleException(
896                                    "No approved JournalArticle exists with the key {groupId=" +
897                                            groupId + ", className=" + className + ", classPK=" +
898                                                    classPK + "}");
899                    }
900    
901                    return articles.get(0);
902            }
903    
904            public JournalArticle getArticleByUrlTitle(long groupId, String urlTitle)
905                    throws PortalException, SystemException {
906    
907                    // Get the latest article that is approved, if none are approved, get
908                    // the latest unapproved article
909    
910                    try {
911                            return getLatestArticleByUrlTitle(
912                                    groupId, urlTitle, WorkflowConstants.STATUS_APPROVED);
913                    }
914                    catch (NoSuchArticleException nsae) {
915                            return getLatestArticleByUrlTitle(
916                                    groupId, urlTitle, WorkflowConstants.STATUS_PENDING);
917                    }
918            }
919    
920            public String getArticleContent(
921                            JournalArticle article, String templateId, String viewMode,
922                            String languageId, ThemeDisplay themeDisplay)
923                    throws PortalException, SystemException {
924    
925                    JournalArticleDisplay articleDisplay = getArticleDisplay(
926                            article, templateId, viewMode, languageId, 1, null, themeDisplay);
927    
928                    if (articleDisplay == null) {
929                            return StringPool.BLANK;
930                    }
931                    else {
932                            return articleDisplay.getContent();
933                    }
934            }
935    
936            public String getArticleContent(
937                            long groupId, String articleId, double version, String viewMode,
938                            String templateId, String languageId, ThemeDisplay themeDisplay)
939                    throws PortalException, SystemException {
940    
941                    JournalArticleDisplay articleDisplay = getArticleDisplay(
942                            groupId, articleId, version, templateId, viewMode, languageId,
943                            themeDisplay);
944    
945                    if (articleDisplay == null) {
946                            return StringPool.BLANK;
947                    }
948                    else {
949                            return articleDisplay.getContent();
950                    }
951            }
952    
953            public String getArticleContent(
954                            long groupId, String articleId, double version, String viewMode,
955                            String languageId, ThemeDisplay themeDisplay)
956                    throws PortalException, SystemException {
957    
958                    return getArticleContent(
959                            groupId, articleId, version, viewMode, null, languageId,
960                            themeDisplay);
961            }
962    
963            public String getArticleContent(
964                            long groupId, String articleId, String viewMode, String templateId,
965                            String languageId, ThemeDisplay themeDisplay)
966                    throws PortalException, SystemException {
967    
968                    JournalArticleDisplay articleDisplay = getArticleDisplay(
969                            groupId, articleId, templateId, viewMode, languageId, themeDisplay);
970    
971                    return articleDisplay.getContent();
972            }
973    
974            public String getArticleContent(
975                            long groupId, String articleId, String viewMode, String languageId,
976                            ThemeDisplay themeDisplay)
977                    throws PortalException, SystemException {
978    
979                    return getArticleContent(
980                            groupId, articleId, viewMode, null, languageId, themeDisplay);
981            }
982    
983            public JournalArticleDisplay getArticleDisplay(
984                            JournalArticle article, String templateId, String viewMode,
985                            String languageId, int page, String xmlRequest,
986                            ThemeDisplay themeDisplay)
987                    throws PortalException, SystemException {
988    
989                    String content = null;
990    
991                    if (page < 1) {
992                            page = 1;
993                    }
994    
995                    int numberOfPages = 1;
996                    boolean paginate = false;
997                    boolean pageFlow = false;
998    
999                    boolean cacheable = true;
1000    
1001                    if (Validator.isNull(xmlRequest)) {
1002                            xmlRequest = "<request />";
1003                    }
1004    
1005                    Map<String, String> tokens = JournalUtil.getTokens(
1006                            article.getGroupId(), themeDisplay, xmlRequest);
1007    
1008                    tokens.put(
1009                            "article_resource_pk",
1010                            String.valueOf(article.getResourcePrimKey()));
1011    
1012                    String defaultTemplateId = article.getTemplateId();
1013    
1014                    if (article.isTemplateDriven()) {
1015                            if (Validator.isNull(templateId)) {
1016                                    templateId = defaultTemplateId;
1017                            }
1018    
1019                            tokens.put("structure_id", article.getStructureId());
1020                            tokens.put("template_id", templateId);
1021                    }
1022    
1023                    String xml = article.getContent();
1024    
1025                    try {
1026                            Document document = null;
1027    
1028                            Element rootElement = null;
1029    
1030                            if (article.isTemplateDriven()) {
1031                                    document = SAXReaderUtil.read(xml);
1032    
1033                                    rootElement = document.getRootElement();
1034    
1035                                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
1036    
1037                                    List<Element> pages = rootElement.elements("page");
1038    
1039                                    if (!pages.isEmpty()) {
1040                                            pageFlow = true;
1041    
1042                                            String targetPage = requestDocument.valueOf(
1043                                                    "/request/parameters/parameter[name='targetPage']/" +
1044                                                            "value");
1045    
1046                                            Element pageElement = null;
1047    
1048                                            if (Validator.isNotNull(targetPage)) {
1049                                                    targetPage = HtmlUtil.escapeXPathAttribute(targetPage);
1050    
1051                                                    XPath xPathSelector = SAXReaderUtil.createXPath(
1052                                                            "/root/page[@id = " + targetPage + "]");
1053    
1054                                                    pageElement = (Element)xPathSelector.selectSingleNode(
1055                                                            document);
1056                                            }
1057    
1058                                            if (pageElement != null) {
1059                                                    document = SAXReaderUtil.createDocument(pageElement);
1060    
1061                                                    rootElement = document.getRootElement();
1062    
1063                                                    numberOfPages = pages.size();
1064                                            }
1065                                            else {
1066                                                    if (page > pages.size()) {
1067                                                            page = 1;
1068                                                    }
1069    
1070                                                    pageElement = pages.get(page - 1);
1071    
1072                                                    document = SAXReaderUtil.createDocument(pageElement);
1073    
1074                                                    rootElement = document.getRootElement();
1075    
1076                                                    numberOfPages = pages.size();
1077                                                    paginate = true;
1078                                            }
1079                                    }
1080    
1081                                    rootElement.add(requestDocument.getRootElement().createCopy());
1082    
1083                                    JournalUtil.addAllReservedEls(
1084                                            rootElement, tokens, article, languageId);
1085    
1086                                    xml = DDMXMLUtil.formatXML(document);
1087                            }
1088                    }
1089                    catch (DocumentException de) {
1090                            throw new SystemException(de);
1091                    }
1092    
1093                    try {
1094                            if (_log.isDebugEnabled()) {
1095                                    _log.debug(
1096                                            "Transforming " + article.getArticleId() + " " +
1097                                                    article.getVersion() + " " + languageId);
1098                            }
1099    
1100                            String script = null;
1101                            String langType = null;
1102    
1103                            if (article.isTemplateDriven()) {
1104    
1105                                    // Try with specified template first (in the current group and
1106                                    // the global group). If a template is not specified, use the
1107                                    // default one. If the specified template does not exit, use the
1108                                    // default one. If the default one does not exist, throw an
1109                                    // exception.
1110    
1111                                    DDMTemplate ddmTtemplate = null;
1112    
1113                                    try {
1114                                            ddmTtemplate = ddmTemplatePersistence.findByG_T(
1115                                                    article.getGroupId(), templateId);
1116                                    }
1117                                    catch (NoSuchTemplateException nste1) {
1118                                            try {
1119                                                    Group companyGroup = groupLocalService.getCompanyGroup(
1120                                                            article.getCompanyId());
1121    
1122                                                    ddmTtemplate = ddmTemplatePersistence.findByG_T(
1123                                                            companyGroup.getGroupId(), templateId);
1124    
1125                                                    tokens.put(
1126                                                            "company_group_id",
1127                                                            String.valueOf(companyGroup.getGroupId()));
1128                                            }
1129                                            catch (NoSuchTemplateException nste2) {
1130                                                    if (!defaultTemplateId.equals(templateId)) {
1131                                                            ddmTtemplate = ddmTemplatePersistence.findByG_T(
1132                                                                    article.getGroupId(), defaultTemplateId);
1133                                                    }
1134                                                    else {
1135                                                            throw nste1;
1136                                                    }
1137                                            }
1138                                    }
1139    
1140                                    script = ddmTtemplate.getScript();
1141                                    langType = ddmTtemplate.getLanguage();
1142                                    cacheable = ddmTtemplate.isCacheable();
1143                            }
1144    
1145                            content = JournalUtil.transform(
1146                                    themeDisplay, tokens, viewMode, languageId, xml, script,
1147                                    langType);
1148    
1149                            if (!pageFlow) {
1150                                    String[] pieces = StringUtil.split(
1151                                            content, PropsValues.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
1152    
1153                                    if (pieces.length > 1) {
1154                                            if (page > pieces.length) {
1155                                                    page = 1;
1156                                            }
1157    
1158                                            content = pieces[page - 1];
1159                                            numberOfPages = pieces.length;
1160                                            paginate = true;
1161                                    }
1162                            }
1163                    }
1164                    catch (Exception e) {
1165                            throw new SystemException(e);
1166                    }
1167    
1168                    return new JournalArticleDisplayImpl(
1169                            article.getCompanyId(), article.getId(),
1170                            article.getResourcePrimKey(), article.getGroupId(),
1171                            article.getUserId(), article.getArticleId(), article.getVersion(),
1172                            article.getTitle(languageId), article.getUrlTitle(),
1173                            article.getDescription(languageId), article.getAvailableLocales(),
1174                            content, article.getType(), article.getStructureId(), templateId,
1175                            article.isSmallImage(), article.getSmallImageId(),
1176                            article.getSmallImageURL(), numberOfPages, page, paginate,
1177                            cacheable);
1178            }
1179    
1180            public JournalArticleDisplay getArticleDisplay(
1181                            long groupId, String articleId, double version, String templateId,
1182                            String viewMode, String languageId, int page, String xmlRequest,
1183                            ThemeDisplay themeDisplay)
1184                    throws PortalException, SystemException {
1185    
1186                    Date now = new Date();
1187    
1188                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1189                            groupId, articleId, version);
1190    
1191                    if (article.isExpired()) {
1192                            Date expirationDate = article.getExpirationDate();
1193    
1194                            if ((expirationDate != null) && expirationDate.before(now)) {
1195                                    return null;
1196                            }
1197                    }
1198    
1199                    if (article.getDisplayDate().after(now)) {
1200                            return null;
1201                    }
1202    
1203                    return getArticleDisplay(
1204                            article, templateId, viewMode, languageId, page, xmlRequest,
1205                            themeDisplay);
1206            }
1207    
1208            public JournalArticleDisplay getArticleDisplay(
1209                            long groupId, String articleId, double version, String templateId,
1210                            String viewMode, String languageId, ThemeDisplay themeDisplay)
1211                    throws PortalException, SystemException {
1212    
1213                    return getArticleDisplay(
1214                            groupId, articleId, version, templateId, viewMode, languageId, 1,
1215                            null, themeDisplay);
1216            }
1217    
1218            public JournalArticleDisplay getArticleDisplay(
1219                            long groupId, String articleId, String viewMode, String languageId,
1220                            int page, String xmlRequest, ThemeDisplay themeDisplay)
1221                    throws PortalException, SystemException {
1222    
1223                    return getArticleDisplay(
1224                            groupId, articleId, null, viewMode, languageId, page, xmlRequest,
1225                            themeDisplay);
1226            }
1227    
1228            public JournalArticleDisplay getArticleDisplay(
1229                            long groupId, String articleId, String templateId, String viewMode,
1230                            String languageId, int page, String xmlRequest,
1231                            ThemeDisplay themeDisplay)
1232                    throws PortalException, SystemException {
1233    
1234                    JournalArticle article = getDisplayArticle(groupId, articleId);
1235    
1236                    return getArticleDisplay(
1237                            groupId, articleId, article.getVersion(), templateId, viewMode,
1238                            languageId, page, xmlRequest, themeDisplay);
1239            }
1240    
1241            public JournalArticleDisplay getArticleDisplay(
1242                            long groupId, String articleId, String templateId, String viewMode,
1243                            String languageId, ThemeDisplay themeDisplay)
1244                    throws PortalException, SystemException {
1245    
1246                    JournalArticle article = getDisplayArticle(groupId, articleId);
1247    
1248                    return getArticleDisplay(
1249                            groupId, articleId, article.getVersion(), templateId, viewMode,
1250                            languageId, themeDisplay);
1251            }
1252    
1253            public JournalArticleDisplay getArticleDisplay(
1254                            long groupId, String articleId, String viewMode, String languageId,
1255                            ThemeDisplay themeDisplay)
1256                    throws PortalException, SystemException {
1257    
1258                    return getArticleDisplay(
1259                            groupId, articleId, null, viewMode, languageId, themeDisplay);
1260            }
1261    
1262            public List<JournalArticle> getArticles() throws SystemException {
1263                    return journalArticlePersistence.findAll();
1264            }
1265    
1266            public List<JournalArticle> getArticles(long groupId)
1267                    throws SystemException {
1268    
1269                    return journalArticlePersistence.findByGroupId(groupId);
1270            }
1271    
1272            public List<JournalArticle> getArticles(long groupId, int start, int end)
1273                    throws SystemException {
1274    
1275                    return journalArticlePersistence.findByGroupId(groupId, start, end);
1276            }
1277    
1278            public List<JournalArticle> getArticles(
1279                            long groupId, int start, int end, OrderByComparator obc)
1280                    throws SystemException {
1281    
1282                    return journalArticlePersistence.findByGroupId(
1283                            groupId, start, end, obc);
1284            }
1285    
1286            public List<JournalArticle> getArticles(long groupId, long folderId)
1287                    throws SystemException {
1288    
1289                    return journalArticlePersistence.findByG_F(groupId, folderId);
1290            }
1291    
1292            public List<JournalArticle> getArticles(
1293                            long groupId, long folderId, int start, int end)
1294                    throws SystemException {
1295    
1296                    return journalArticlePersistence.findByG_F(
1297                            groupId, folderId, start, end);
1298            }
1299    
1300            public List<JournalArticle> getArticles(
1301                            long groupId, long folderId, int start, int end,
1302                            OrderByComparator orderByComparator)
1303                    throws SystemException {
1304    
1305                    return journalArticlePersistence.findByG_F(
1306                            groupId, folderId, start, end, orderByComparator);
1307            }
1308    
1309            public List<JournalArticle> getArticles(long groupId, String articleId)
1310                    throws SystemException {
1311    
1312                    return journalArticlePersistence.findByG_A(groupId, articleId);
1313            }
1314    
1315            public List<JournalArticle> getArticlesBySmallImageId(long smallImageId)
1316                    throws SystemException {
1317    
1318                    return journalArticlePersistence.findBySmallImageId(smallImageId);
1319            }
1320    
1321            public int getArticlesCount(long groupId) throws SystemException {
1322                    return journalArticlePersistence.countByGroupId(groupId);
1323            }
1324    
1325            public int getArticlesCount(long groupId, long folderId)
1326                    throws SystemException {
1327    
1328                    return journalArticlePersistence.countByG_F(groupId, folderId);
1329            }
1330    
1331            public List<JournalArticle> getCompanyArticles(
1332                            long companyId, double version, int status, int start, int end)
1333                    throws SystemException {
1334    
1335                    if (status == WorkflowConstants.STATUS_ANY) {
1336                            return journalArticlePersistence.findByC_V(
1337                                    companyId, version, start, end, new ArticleIDComparator(true));
1338                    }
1339                    else {
1340                            return journalArticlePersistence.findByC_V_ST(
1341                                    companyId, version, status, start, end,
1342                                    new ArticleIDComparator(true));
1343                    }
1344            }
1345    
1346            public List<JournalArticle> getCompanyArticles(
1347                            long companyId, int status, int start, int end)
1348                    throws SystemException {
1349    
1350                    if (status == WorkflowConstants.STATUS_ANY) {
1351                            return journalArticlePersistence.findByCompanyId(
1352                                    companyId, start, end, new ArticleIDComparator(true));
1353                    }
1354                    else {
1355                            return journalArticlePersistence.findByC_ST(
1356                                    companyId, status, start, end, new ArticleIDComparator(true));
1357                    }
1358            }
1359    
1360            public int getCompanyArticlesCount(
1361                            long companyId, double version, int status, int start, int end)
1362                    throws SystemException {
1363    
1364                    if (status == WorkflowConstants.STATUS_ANY) {
1365                            return journalArticlePersistence.countByC_V(companyId, version);
1366                    }
1367                    else {
1368                            return journalArticlePersistence.countByC_V_ST(
1369                                    companyId, version, status);
1370                    }
1371            }
1372    
1373            public int getCompanyArticlesCount(long companyId, int status)
1374                    throws SystemException {
1375    
1376                    if (status == WorkflowConstants.STATUS_ANY) {
1377                            return journalArticlePersistence.countByCompanyId(companyId);
1378                    }
1379                    else {
1380                            return journalArticlePersistence.countByC_ST(companyId, status);
1381                    }
1382            }
1383    
1384            public JournalArticle getDisplayArticle(long groupId, String articleId)
1385                    throws PortalException, SystemException {
1386    
1387                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
1388                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1389    
1390                    if (articles.isEmpty()) {
1391                            throw new NoSuchArticleException(
1392                                    "No approved JournalArticle exists with the key {groupId=" +
1393                                            groupId + ", " + "articleId=" + articleId + "}");
1394    
1395                    }
1396    
1397                    Date now = new Date();
1398    
1399                    for (int i = 0; i < articles.size(); i++) {
1400                            JournalArticle article = articles.get(i);
1401    
1402                            Date expirationDate = article.getExpirationDate();
1403    
1404                            if (article.getDisplayDate().before(now) &&
1405                                    ((expirationDate == null) || expirationDate.after(now))) {
1406    
1407                                    return article;
1408                            }
1409                    }
1410    
1411                    return articles.get(0);
1412            }
1413    
1414            public JournalArticle getDisplayArticleByUrlTitle(
1415                            long groupId, String urlTitle)
1416                    throws PortalException, SystemException {
1417    
1418                    List<JournalArticle> articles = null;
1419    
1420                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1421    
1422                    articles = journalArticlePersistence.findByG_UT_ST(
1423                            groupId, urlTitle, WorkflowConstants.STATUS_APPROVED,
1424                            QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
1425    
1426                    if (articles.isEmpty()) {
1427                            throw new NoSuchArticleException(
1428                                    "No JournalArticle exists with the key {groupId=" + groupId +
1429                                            ", urlTitle=" + urlTitle + "}");
1430                    }
1431    
1432                    Date now = new Date();
1433    
1434                    for (JournalArticle article : articles) {
1435                            Date expirationDate = article.getExpirationDate();
1436    
1437                            if (article.getDisplayDate().before(now) &&
1438                                    ((expirationDate == null) || expirationDate.after(now))) {
1439    
1440                                    return article;
1441                            }
1442                    }
1443    
1444                    return articles.get(0);
1445            }
1446    
1447            public JournalArticle getLatestArticle(long resourcePrimKey)
1448                    throws PortalException, SystemException {
1449    
1450                    return getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
1451            }
1452    
1453            public JournalArticle getLatestArticle(long resourcePrimKey, int status)
1454                    throws PortalException, SystemException {
1455    
1456                    return getLatestArticle(resourcePrimKey, status, true);
1457            }
1458    
1459            public JournalArticle getLatestArticle(
1460                            long resourcePrimKey, int status, boolean preferApproved)
1461                    throws PortalException, SystemException {
1462    
1463                    List<JournalArticle> articles = null;
1464    
1465                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1466    
1467                    if (status == WorkflowConstants.STATUS_ANY) {
1468                            if (preferApproved) {
1469                                    articles = journalArticlePersistence.findByR_ST(
1470                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED, 0, 1,
1471                                            orderByComparator);
1472                            }
1473    
1474                            if ((articles == null) || (articles.size() == 0)) {
1475                                    articles = journalArticlePersistence.findByResourcePrimKey(
1476                                            resourcePrimKey, 0, 1, orderByComparator);
1477                            }
1478                    }
1479                    else {
1480                            articles = journalArticlePersistence.findByR_ST(
1481                                    resourcePrimKey, status, 0, 1, orderByComparator);
1482                    }
1483    
1484                    if (articles.isEmpty()) {
1485                            throw new NoSuchArticleException(
1486                                    "No JournalArticle exists with the key {resourcePrimKey=" +
1487                                            resourcePrimKey + "}");
1488                    }
1489    
1490                    return articles.get(0);
1491            }
1492    
1493            public JournalArticle getLatestArticle(long groupId, String articleId)
1494                    throws PortalException, SystemException {
1495    
1496                    return getLatestArticle(
1497                            groupId, articleId, WorkflowConstants.STATUS_ANY);
1498            }
1499    
1500            public JournalArticle getLatestArticle(
1501                            long groupId, String articleId, int status)
1502                    throws PortalException, SystemException {
1503    
1504                    List<JournalArticle> articles = null;
1505    
1506                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1507    
1508                    if (status == WorkflowConstants.STATUS_ANY) {
1509                            articles = journalArticlePersistence.findByG_A(
1510                                    groupId, articleId, 0, 1, orderByComparator);
1511                    }
1512                    else {
1513                            articles = journalArticlePersistence.findByG_A_ST(
1514                                    groupId, articleId, status, 0, 1, orderByComparator);
1515                    }
1516    
1517                    if (articles.isEmpty()) {
1518                            throw new NoSuchArticleException(
1519                                    "No JournalArticle exists with the key {groupId=" + groupId +
1520                                            ", articleId=" + articleId + ", status=" + status + "}");
1521                    }
1522    
1523                    return articles.get(0);
1524            }
1525    
1526            public JournalArticle getLatestArticle(
1527                            long groupId, String className, long classPK)
1528                    throws PortalException, SystemException {
1529    
1530                    long classNameId = PortalUtil.getClassNameId(className);
1531    
1532                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
1533                            groupId, classNameId, classPK, 0, 1,
1534                            new ArticleVersionComparator());
1535    
1536                    if (articles.isEmpty()) {
1537                            throw new NoSuchArticleException(
1538                                    "No JournalArticle exists with the key {groupId=" + groupId +
1539                                            ", className=" + className + ", classPK =" + classPK + "}");
1540                    }
1541    
1542                    return articles.get(0);
1543            }
1544    
1545            public JournalArticle getLatestArticleByUrlTitle(
1546                            long groupId, String urlTitle, int status)
1547                    throws PortalException, SystemException {
1548    
1549                    List<JournalArticle> articles = null;
1550    
1551                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1552    
1553                    if (status == WorkflowConstants.STATUS_ANY) {
1554                            articles = journalArticlePersistence.findByG_UT(
1555                                    groupId, urlTitle, 0, 1, orderByComparator);
1556                    }
1557                    else {
1558                            articles = journalArticlePersistence.findByG_UT_ST(
1559                                    groupId, urlTitle, status, 0, 1, orderByComparator);
1560                    }
1561    
1562                    if (articles.isEmpty()) {
1563                            throw new NoSuchArticleException(
1564                                    "No JournalArticle exists with the key {groupId=" + groupId +
1565                                            ", urlTitle=" + urlTitle + ", status=" + status + "}");
1566                    }
1567    
1568                    return articles.get(0);
1569            }
1570    
1571            public double getLatestVersion(long groupId, String articleId)
1572                    throws PortalException, SystemException {
1573    
1574                    JournalArticle article = getLatestArticle(groupId, articleId);
1575    
1576                    return article.getVersion();
1577            }
1578    
1579            public double getLatestVersion(long groupId, String articleId, int status)
1580                    throws PortalException, SystemException {
1581    
1582                    JournalArticle article = getLatestArticle(groupId, articleId, status);
1583    
1584                    return article.getVersion();
1585            }
1586    
1587            public List<JournalArticle> getStructureArticles(
1588                            long groupId, String structureId)
1589                    throws SystemException {
1590    
1591                    return journalArticlePersistence.findByG_S(groupId, structureId);
1592            }
1593    
1594            public List<JournalArticle> getStructureArticles(
1595                            long groupId, String structureId, int start, int end,
1596                            OrderByComparator obc)
1597                    throws SystemException {
1598    
1599                    return journalArticlePersistence.findByG_S(
1600                            groupId, structureId, start, end, obc);
1601            }
1602    
1603            public int getStructureArticlesCount(long groupId, String structureId)
1604                    throws SystemException {
1605    
1606                    return journalArticlePersistence.countByG_S(groupId, structureId);
1607            }
1608    
1609            public List<JournalArticle> getTemplateArticles(
1610                            long groupId, String templateId)
1611                    throws SystemException {
1612    
1613                    return journalArticlePersistence.findByG_T(groupId, templateId);
1614            }
1615    
1616            public List<JournalArticle> getTemplateArticles(
1617                            long groupId, String templateId, int start, int end,
1618                            OrderByComparator obc)
1619                    throws SystemException {
1620    
1621                    return journalArticlePersistence.findByG_T(
1622                            groupId, templateId, start, end, obc);
1623            }
1624    
1625            public int getTemplateArticlesCount(long groupId, String templateId)
1626                    throws SystemException {
1627    
1628                    return journalArticlePersistence.countByG_T(groupId, templateId);
1629            }
1630    
1631            public boolean hasArticle(long groupId, String articleId)
1632                    throws SystemException {
1633    
1634                    try {
1635                            getArticle(groupId, articleId);
1636    
1637                            return true;
1638                    }
1639                    catch (PortalException pe) {
1640                            return false;
1641                    }
1642            }
1643    
1644            public boolean isLatestVersion(
1645                            long groupId, String articleId, double version)
1646                    throws PortalException, SystemException {
1647    
1648                    if (getLatestVersion(groupId, articleId) == version) {
1649                            return true;
1650                    }
1651                    else {
1652                            return false;
1653                    }
1654            }
1655    
1656            public boolean isLatestVersion(
1657                            long groupId, String articleId, double version, int status)
1658                    throws PortalException, SystemException {
1659    
1660                    if (getLatestVersion(groupId, articleId, status) == version) {
1661                            return true;
1662                    }
1663                    else {
1664                            return false;
1665                    }
1666            }
1667    
1668            public void moveArticle(long groupId, String articleId, long newFolderId)
1669                    throws SystemException {
1670    
1671                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
1672                            groupId, articleId);
1673    
1674                    for (JournalArticle article : articles) {
1675                            article.setFolderId(newFolderId);
1676    
1677                            journalArticlePersistence.update(article);
1678                    }
1679            }
1680    
1681            public JournalArticle removeArticleLocale(
1682                            long groupId, String articleId, double version, String languageId)
1683                    throws PortalException, SystemException {
1684    
1685                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1686                            groupId, articleId, version);
1687    
1688                    String title = article.getTitle();
1689    
1690                    title = LocalizationUtil.removeLocalization(
1691                            title, "static-content", languageId, true);
1692    
1693                    article.setTitle(title);
1694    
1695                    String description = article.getDescription();
1696    
1697                    description = LocalizationUtil.removeLocalization(
1698                            description, "static-content", languageId, true);
1699    
1700                    article.setDescription(description);
1701    
1702                    String content = article.getContent();
1703    
1704                    if (article.isTemplateDriven()) {
1705                            content = JournalUtil.removeArticleLocale(content, languageId);
1706                    }
1707                    else {
1708                            content = LocalizationUtil.removeLocalization(
1709                                    content, "static-content", languageId, true);
1710                    }
1711    
1712                    article.setContent(content);
1713    
1714                    journalArticlePersistence.update(article);
1715    
1716                    return article;
1717            }
1718    
1719            public List<JournalArticle> search(
1720                            long companyId, long groupId, List<Long> folderIds,
1721                            long classNameId, String keywords, Double version, String type,
1722                            String structureId, String templateId, Date displayDateGT,
1723                            Date displayDateLT, int status, Date reviewDate, int start, int end,
1724                            OrderByComparator obc)
1725                    throws SystemException {
1726    
1727                    return journalArticleFinder.findByKeywords(
1728                            companyId, groupId, folderIds, classNameId, keywords, version, type,
1729                            structureId, templateId, displayDateGT, displayDateLT, status,
1730                            reviewDate, start, end, obc);
1731            }
1732    
1733            public List<JournalArticle> search(
1734                            long companyId, long groupId, List<Long> folderIds,
1735                            long classNameId, String articleId, Double version, String title,
1736                            String description, String content, String type, String structureId,
1737                            String templateId, Date displayDateGT, Date displayDateLT,
1738                            int status, Date reviewDate, boolean andOperator, int start,
1739                            int end, OrderByComparator obc)
1740                    throws SystemException {
1741    
1742                    return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_S_R(
1743                            companyId, groupId, folderIds, classNameId, articleId, version,
1744                            title, description, content, type, structureId, templateId,
1745                            displayDateGT, displayDateLT, status, reviewDate, andOperator,
1746                            start, end, obc);
1747            }
1748    
1749            public List<JournalArticle> search(
1750                            long companyId, long groupId, List<Long> folderIds,
1751                            long classNameId, String articleId, Double version, String title,
1752                            String description, String content, String type,
1753                            String[] structureIds, String[] templateIds, Date displayDateGT,
1754                            Date displayDateLT, int status, Date reviewDate,
1755                            boolean andOperator, int start, int end, OrderByComparator obc)
1756                    throws SystemException {
1757    
1758                    return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_S_R(
1759                            companyId, groupId, folderIds, classNameId, articleId, version,
1760                            title, description, content, type, structureIds, templateIds,
1761                            displayDateGT, displayDateLT, status, reviewDate, andOperator,
1762                            start, end, obc);
1763            }
1764    
1765            public Hits search(
1766                            long companyId, long groupId, List<Long> folderIds,
1767                            long classNameId, String structureId, String templateId,
1768                            String keywords, LinkedHashMap<String, Object> params, int start,
1769                            int end, Sort sort)
1770                    throws SystemException {
1771    
1772                    String articleId = null;
1773                    String title = null;
1774                    String description = null;
1775                    String content = null;
1776                    boolean andOperator = false;
1777    
1778                    if (Validator.isNotNull(keywords)) {
1779                            articleId = keywords;
1780                            title = keywords;
1781                            description = keywords;
1782                            content = keywords;
1783                    }
1784                    else {
1785                            andOperator = true;
1786                    }
1787    
1788                    String status = String.valueOf(WorkflowConstants.STATUS_ANY);
1789    
1790                    if (params != null) {
1791                            params.put("keywords", keywords);
1792                    }
1793    
1794                    return search(
1795                            companyId, groupId, folderIds, classNameId, articleId, title,
1796                            description, content, null, status, structureId, templateId, params,
1797                            andOperator, start, end, sort);
1798            }
1799    
1800            public Hits search(
1801                            long companyId, long groupId, List<Long> folderIds,
1802                            long classNameId, String articleId, String title,
1803                            String description, String content, String type, String status,
1804                            String structureId, String templateId,
1805                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
1806                            int end, Sort sort)
1807                    throws SystemException {
1808    
1809                    try {
1810                            SearchContext searchContext = new SearchContext();
1811    
1812                            searchContext.setAndSearch(andSearch);
1813    
1814                            Map<String, Serializable> attributes =
1815                                    new HashMap<String, Serializable>();
1816    
1817                            attributes.put(Field.CLASS_NAME_ID, classNameId);
1818                            attributes.put(Field.CONTENT, content);
1819                            attributes.put(Field.DESCRIPTION, description);
1820                            attributes.put(Field.STATUS, status);
1821                            attributes.put(Field.TITLE, title);
1822                            attributes.put(Field.TYPE, type);
1823                            attributes.put("articleId", articleId);
1824                            attributes.put("params", params);
1825                            attributes.put("structureId", structureId);
1826                            attributes.put("templateId", templateId);
1827    
1828                            searchContext.setAttributes(attributes);
1829    
1830                            searchContext.setCompanyId(companyId);
1831                            searchContext.setEnd(end);
1832                            searchContext.setFolderIds(folderIds);
1833                            searchContext.setGroupIds(new long[] {groupId});
1834    
1835                            if (params != null) {
1836                                    String keywords = (String)params.remove("keywords");
1837    
1838                                    if (Validator.isNotNull(keywords)) {
1839                                            searchContext.setKeywords(keywords);
1840                                    }
1841                            }
1842    
1843                            QueryConfig queryConfig = new QueryConfig();
1844    
1845                            queryConfig.setHighlightEnabled(false);
1846                            queryConfig.setScoreEnabled(false);
1847    
1848                            searchContext.setQueryConfig(queryConfig);
1849    
1850                            if (sort != null) {
1851                                    searchContext.setSorts(new Sort[] {sort});
1852                            }
1853    
1854                            searchContext.setStart(start);
1855    
1856                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1857                                    JournalArticle.class);
1858    
1859                            return indexer.search(searchContext);
1860                    }
1861                    catch (Exception e) {
1862                            throw new SystemException(e);
1863                    }
1864            }
1865    
1866            public int searchCount(
1867                            long companyId, long groupId, List<Long> folderIds,
1868                            long classNameId, String keywords, Double version, String type,
1869                            String structureId, String templateId, Date displayDateGT,
1870                            Date displayDateLT, int status, Date reviewDate)
1871                    throws SystemException {
1872    
1873                    return journalArticleFinder.countByKeywords(
1874                            companyId, groupId, folderIds, classNameId, keywords, version, type,
1875                            structureId, templateId, displayDateGT, displayDateLT, status,
1876                            reviewDate);
1877            }
1878    
1879            public int searchCount(
1880                            long companyId, long groupId, List<Long> folderIds,
1881                            long classNameId, String articleId, Double version, String title,
1882                            String description, String content, String type, String structureId,
1883                            String templateId, Date displayDateGT, Date displayDateLT,
1884                            int status, Date reviewDate, boolean andOperator)
1885                    throws SystemException {
1886    
1887                    return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_S_R(
1888                            companyId, groupId, folderIds, classNameId, articleId, version,
1889                            title, description, content, type, structureId, templateId,
1890                            displayDateGT, displayDateLT, status, reviewDate, andOperator);
1891            }
1892    
1893            public int searchCount(
1894                            long companyId, long groupId, List<Long> folderIds,
1895                            long classNameId, String articleId, Double version, String title,
1896                            String description, String content, String type,
1897                            String[] structureIds, String[] templateIds, Date displayDateGT,
1898                            Date displayDateLT, int status, Date reviewDate,
1899                            boolean andOperator)
1900                    throws SystemException {
1901    
1902                    return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_S_R(
1903                            companyId, groupId, folderIds, classNameId, articleId, version,
1904                            title, description, content, type, structureIds, templateIds,
1905                            displayDateGT, displayDateLT, status, reviewDate, andOperator);
1906            }
1907    
1908            public void subscribe(long userId, long groupId)
1909                    throws PortalException, SystemException {
1910    
1911                    subscriptionLocalService.addSubscription(
1912                            userId, groupId, JournalArticle.class.getName(), groupId);
1913            }
1914    
1915            public void unsubscribe(long userId, long groupId)
1916                    throws PortalException, SystemException {
1917    
1918                    subscriptionLocalService.deleteSubscription(
1919                            userId, JournalArticle.class.getName(), groupId);
1920            }
1921    
1922            public JournalArticle updateArticle(
1923                            long userId, long groupId, long folderId, String articleId,
1924                            double version, Map<Locale, String> titleMap,
1925                            Map<Locale, String> descriptionMap, String content,
1926                            String layoutUuid, ServiceContext serviceContext)
1927                    throws PortalException, SystemException {
1928    
1929                    User user = userPersistence.findByPrimaryKey(userId);
1930    
1931                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1932                            groupId, articleId, version);
1933    
1934                    Date displayDate = article.getDisplayDate();
1935    
1936                    int displayDateMonth = 0;
1937                    int displayDateDay = 0;
1938                    int displayDateYear = 0;
1939                    int displayDateHour = 0;
1940                    int displayDateMinute = 0;
1941    
1942                    if (displayDate != null) {
1943                            Calendar displayCal = CalendarFactoryUtil.getCalendar(
1944                                    user.getTimeZone());
1945    
1946                            displayCal.setTime(displayDate);
1947    
1948                            displayDateMonth = displayCal.get(Calendar.MONTH);
1949                            displayDateDay = displayCal.get(Calendar.DATE);
1950                            displayDateYear = displayCal.get(Calendar.YEAR);
1951                            displayDateHour = displayCal.get(Calendar.HOUR);
1952                            displayDateMinute = displayCal.get(Calendar.MINUTE);
1953    
1954                            if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
1955                                    displayDateHour += 12;
1956                            }
1957                    }
1958    
1959                    Date expirationDate = article.getExpirationDate();
1960    
1961                    int expirationDateMonth = 0;
1962                    int expirationDateDay = 0;
1963                    int expirationDateYear = 0;
1964                    int expirationDateHour = 0;
1965                    int expirationDateMinute = 0;
1966                    boolean neverExpire = true;
1967    
1968                    if (expirationDate != null) {
1969                            Calendar expirationCal = CalendarFactoryUtil.getCalendar(
1970                                    user.getTimeZone());
1971    
1972                            expirationCal.setTime(expirationDate);
1973    
1974                            expirationDateMonth = expirationCal.get(Calendar.MONTH);
1975                            expirationDateDay = expirationCal.get(Calendar.DATE);
1976                            expirationDateYear = expirationCal.get(Calendar.YEAR);
1977                            expirationDateHour = expirationCal.get(Calendar.HOUR);
1978                            expirationDateMinute = expirationCal.get(Calendar.MINUTE);
1979                            neverExpire = false;
1980    
1981                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
1982                                    expirationDateHour += 12;
1983                            }
1984                    }
1985    
1986                    Date reviewDate = article.getReviewDate();
1987    
1988                    int reviewDateMonth = 0;
1989                    int reviewDateDay = 0;
1990                    int reviewDateYear = 0;
1991                    int reviewDateHour = 0;
1992                    int reviewDateMinute = 0;
1993                    boolean neverReview = true;
1994    
1995                    if (reviewDate != null) {
1996                            Calendar reviewCal = CalendarFactoryUtil.getCalendar(
1997                                    user.getTimeZone());
1998    
1999                            reviewCal.setTime(reviewDate);
2000    
2001                            reviewDateMonth = reviewCal.get(Calendar.MONTH);
2002                            reviewDateDay = reviewCal.get(Calendar.DATE);
2003                            reviewDateYear = reviewCal.get(Calendar.YEAR);
2004                            reviewDateHour = reviewCal.get(Calendar.HOUR);
2005                            reviewDateMinute = reviewCal.get(Calendar.MINUTE);
2006                            neverReview = false;
2007    
2008                            if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
2009                                    reviewDateHour += 12;
2010                            }
2011                    }
2012    
2013                    return updateArticle(
2014                            userId, groupId, folderId, articleId, version, titleMap,
2015                            descriptionMap, content, article.getType(),
2016                            article.getStructureId(), article.getTemplateId(), layoutUuid,
2017                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
2018                            displayDateMinute, expirationDateMonth, expirationDateDay,
2019                            expirationDateYear, expirationDateHour, expirationDateMinute,
2020                            neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
2021                            reviewDateHour, reviewDateMinute, neverReview,
2022                            article.getIndexable(), article.isSmallImage(),
2023                            article.getSmallImageURL(), null, null, null, serviceContext);
2024            }
2025    
2026            public JournalArticle updateArticle(
2027                            long userId, long groupId, long folderId, String articleId,
2028                            double version, Map<Locale, String> titleMap,
2029                            Map<Locale, String> descriptionMap, String content, String type,
2030                            String structureId, String templateId, String layoutUuid,
2031                            int displayDateMonth, int displayDateDay, int displayDateYear,
2032                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
2033                            int expirationDateDay, int expirationDateYear,
2034                            int expirationDateHour, int expirationDateMinute,
2035                            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
2036                            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
2037                            boolean neverReview, boolean indexable, boolean smallImage,
2038                            String smallImageURL, File smallImageFile,
2039                            Map<String, byte[]> images, String articleURL,
2040                            ServiceContext serviceContext)
2041                    throws PortalException, SystemException {
2042    
2043                    // Article
2044    
2045                    User user = userPersistence.findByPrimaryKey(userId);
2046                    articleId = articleId.trim().toUpperCase();
2047    
2048                    byte[] smallImageBytes = null;
2049    
2050                    try {
2051                            smallImageBytes = FileUtil.getBytes(smallImageFile);
2052                    }
2053                    catch (IOException ioe) {
2054                    }
2055    
2056                    JournalArticle latestArticle = getLatestArticle(
2057                            groupId, articleId, WorkflowConstants.STATUS_ANY);
2058    
2059                    JournalArticle article = latestArticle;
2060    
2061                    boolean imported = ImportExportThreadLocal.isImportInProcess();
2062    
2063                    double latestVersion = latestArticle.getVersion();
2064    
2065                    boolean addNewVersion = false;
2066    
2067                    if (imported) {
2068                            if (latestVersion > version) {
2069                                    JournalArticle existingArticle =
2070                                            journalArticlePersistence.fetchByG_A_V(
2071                                                    groupId, articleId, version);
2072    
2073                                    if (existingArticle != null) {
2074                                            article = existingArticle;
2075                                    }
2076                                    else {
2077                                            addNewVersion = true;
2078                                    }
2079                            }
2080                            else if (latestVersion < version) {
2081                                    addNewVersion = true;
2082                            }
2083                    }
2084                    else {
2085                            if ((version > 0) && (version != latestVersion)) {
2086                                    throw new ArticleVersionException();
2087                            }
2088    
2089                            serviceContext.validateModifiedDate(
2090                                    latestArticle, ArticleVersionException.class);
2091    
2092                            if (latestArticle.isApproved() || latestArticle.isExpired()) {
2093                                    addNewVersion = true;
2094    
2095                                    version = MathUtil.format(latestVersion + 0.1, 1, 1);
2096                            }
2097                    }
2098    
2099                    Date displayDate = null;
2100                    Date expirationDate = null;
2101                    Date reviewDate = null;
2102    
2103                    if (article.getClassNameId() ==
2104                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2105    
2106                            displayDate = PortalUtil.getDate(
2107                                    displayDateMonth, displayDateDay, displayDateYear,
2108                                    displayDateHour, displayDateMinute, user.getTimeZone(),
2109                                    ArticleDisplayDateException.class);
2110    
2111                            if (!neverExpire) {
2112                                    expirationDate = PortalUtil.getDate(
2113                                            expirationDateMonth, expirationDateDay, expirationDateYear,
2114                                            expirationDateHour, expirationDateMinute,
2115                                            user.getTimeZone(), ArticleExpirationDateException.class);
2116                            }
2117    
2118                            if (!neverReview) {
2119                                    reviewDate = PortalUtil.getDate(
2120                                            reviewDateMonth, reviewDateDay, reviewDateYear,
2121                                            reviewDateHour, reviewDateMinute, user.getTimeZone(),
2122                                            ArticleReviewDateException.class);
2123                            }
2124                    }
2125    
2126                    Date now = new Date();
2127    
2128                    boolean expired = false;
2129    
2130                    if ((expirationDate != null) && expirationDate.before(now)) {
2131                            expired = true;
2132                    }
2133    
2134                    validate(
2135                            user.getCompanyId(), groupId, latestArticle.getClassNameId(),
2136                            titleMap, content, type, structureId, templateId, expirationDate,
2137                            smallImage, smallImageURL, smallImageFile, smallImageBytes);
2138    
2139                    if (addNewVersion) {
2140                            long id = counterLocalService.increment();
2141    
2142                            article = journalArticlePersistence.create(id);
2143    
2144                            article.setResourcePrimKey(latestArticle.getResourcePrimKey());
2145                            article.setGroupId(latestArticle.getGroupId());
2146                            article.setCompanyId(latestArticle.getCompanyId());
2147                            article.setUserId(user.getUserId());
2148                            article.setUserName(user.getFullName());
2149                            article.setCreateDate(serviceContext.getModifiedDate(now));
2150                            article.setClassNameId(latestArticle.getClassNameId());
2151                            article.setClassPK(latestArticle.getClassPK());
2152                            article.setArticleId(articleId);
2153                            article.setVersion(version);
2154                            article.setSmallImageId(latestArticle.getSmallImageId());
2155                    }
2156    
2157                    Locale locale = LocaleUtil.getDefault();
2158    
2159                    String defaultLanguageId = ParamUtil.getString(
2160                            serviceContext, "defaultLanguageId");
2161    
2162                    if (Validator.isNull(defaultLanguageId)) {
2163                            defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
2164                    }
2165    
2166                    if (Validator.isNotNull(defaultLanguageId)) {
2167                            locale = LocaleUtil.fromLanguageId(defaultLanguageId);
2168                    }
2169    
2170                    String title = titleMap.get(locale);
2171    
2172                    content = format(
2173                            user, groupId, articleId, article.getVersion(), addNewVersion,
2174                            content, structureId, images);
2175    
2176                    article.setModifiedDate(serviceContext.getModifiedDate(now));
2177                    article.setFolderId(folderId);
2178                    article.setTitleMap(titleMap, locale);
2179                    article.setUrlTitle(
2180                            getUniqueUrlTitle(
2181                                    article.getId(), article.getArticleId(), title,
2182                                    latestArticle.getUrlTitle(), serviceContext));
2183                    article.setDescriptionMap(descriptionMap, locale);
2184                    article.setContent(content);
2185                    article.setType(type);
2186                    article.setStructureId(structureId);
2187                    article.setTemplateId(templateId);
2188                    article.setLayoutUuid(layoutUuid);
2189                    article.setDisplayDate(displayDate);
2190                    article.setExpirationDate(expirationDate);
2191                    article.setReviewDate(reviewDate);
2192                    article.setIndexable(indexable);
2193                    article.setSmallImage(smallImage);
2194    
2195                    if (smallImage) {
2196                            if ((smallImageFile != null) && (smallImageBytes != null)) {
2197                                    article.setSmallImageId(counterLocalService.increment());
2198                            }
2199                    }
2200                    else {
2201                            article.setSmallImageId(0);
2202                    }
2203    
2204                    article.setSmallImageURL(smallImageURL);
2205    
2206                    if (latestArticle.isPending()) {
2207                            article.setStatus(latestArticle.getStatus());
2208                    }
2209                    else if (!expired) {
2210                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
2211                    }
2212                    else {
2213                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
2214                    }
2215    
2216                    journalArticlePersistence.update(article);
2217    
2218                    // Asset
2219    
2220                    updateAsset(
2221                            userId, article, serviceContext.getAssetCategoryIds(),
2222                            serviceContext.getAssetTagNames(),
2223                            serviceContext.getAssetLinkEntryIds());
2224    
2225                    // Expando
2226    
2227                    ExpandoBridge expandoBridge = article.getExpandoBridge();
2228    
2229                    expandoBridge.setAttributes(serviceContext);
2230    
2231                    // Small image
2232    
2233                    saveImages(
2234                            smallImage, article.getSmallImageId(), smallImageFile,
2235                            smallImageBytes);
2236    
2237                    // Email
2238    
2239                    PortletPreferences preferences =
2240                            ServiceContextUtil.getPortletPreferences(serviceContext);
2241    
2242                    // Workflow
2243    
2244                    if (expired && imported) {
2245                            updateStatus(
2246                                    userId, article, article.getStatus(), articleURL,
2247                                    serviceContext);
2248                    }
2249    
2250                    if (serviceContext.getWorkflowAction() ==
2251                                    WorkflowConstants.ACTION_PUBLISH) {
2252    
2253                            sendEmail(
2254                                    article, articleURL, preferences, "requested", serviceContext);
2255    
2256                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
2257                                    user.getCompanyId(), groupId, userId,
2258                                    JournalArticle.class.getName(), article.getId(), article,
2259                                    serviceContext);
2260                    }
2261                    else if (article.getVersion() ==
2262                                            JournalArticleConstants.VERSION_DEFAULT) {
2263    
2264                            // Indexer
2265    
2266                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2267                                    JournalArticle.class);
2268    
2269                            indexer.reindex(article);
2270                    }
2271    
2272                    return article;
2273            }
2274    
2275            public JournalArticle updateArticle(
2276                            long userId, long groupId, long folderId, String articleId,
2277                            double version, String content, ServiceContext serviceContext)
2278                    throws PortalException, SystemException {
2279    
2280                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2281                            groupId, articleId, version);
2282    
2283                    return updateArticle(
2284                            userId, groupId, folderId, articleId, version,
2285                            article.getTitleMap(), article.getDescriptionMap(), content,
2286                            article.getLayoutUuid(), serviceContext);
2287            }
2288    
2289            /**
2290             * @deprecated {@link #updateArticleTranslation(long, String, double,
2291             *             Locale, String, String, String, Map, ServiceContext)}
2292             */
2293            public JournalArticle updateArticleTranslation(
2294                            long groupId, String articleId, double version, Locale locale,
2295                            String title, String description, String content,
2296                            Map<String, byte[]> images)
2297                    throws PortalException, SystemException {
2298    
2299                    return updateArticleTranslation(
2300                            groupId, articleId, version, locale, title, description, content,
2301                            images, null);
2302            }
2303    
2304            public JournalArticle updateArticleTranslation(
2305                            long groupId, String articleId, double version, Locale locale,
2306                            String title, String description, String content,
2307                            Map<String, byte[]> images, ServiceContext serviceContext)
2308                    throws PortalException, SystemException {
2309    
2310                    validateContent(content);
2311    
2312                    JournalArticle oldArticle = getLatestArticle(
2313                            groupId, articleId, WorkflowConstants.STATUS_ANY);
2314    
2315                    double oldVersion = oldArticle.getVersion();
2316    
2317                    if ((version > 0) && (version != oldVersion)) {
2318                            throw new ArticleVersionException();
2319                    }
2320    
2321                    boolean incrementVersion = false;
2322    
2323                    if (oldArticle.isApproved() || oldArticle.isExpired()) {
2324                            incrementVersion = true;
2325                    }
2326    
2327                    if (serviceContext != null) {
2328                            serviceContext.validateModifiedDate(
2329                                    oldArticle, ArticleVersionException.class);
2330                    }
2331    
2332                    JournalArticle article = null;
2333    
2334                    User user = userPersistence.findByPrimaryKey(oldArticle.getUserId());
2335    
2336                    if (incrementVersion) {
2337                            double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
2338    
2339                            long id = counterLocalService.increment();
2340    
2341                            article = journalArticlePersistence.create(id);
2342    
2343                            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
2344                            article.setGroupId(oldArticle.getGroupId());
2345                            article.setCompanyId(oldArticle.getCompanyId());
2346                            article.setUserId(oldArticle.getUserId());
2347                            article.setUserName(user.getFullName());
2348                            article.setCreateDate(new Date());
2349                            article.setModifiedDate(new Date());
2350                            article.setClassNameId(oldArticle.getClassNameId());
2351                            article.setClassPK(oldArticle.getClassPK());
2352                            article.setArticleId(articleId);
2353                            article.setVersion(newVersion);
2354                            article.setTitleMap(oldArticle.getTitleMap());
2355                            article.setUrlTitle(
2356                                    getUniqueUrlTitle(
2357                                            id, articleId, title, oldArticle.getUrlTitle(),
2358                                            serviceContext));
2359                            article.setDescriptionMap(oldArticle.getDescriptionMap());
2360                            article.setType(oldArticle.getType());
2361                            article.setStructureId(oldArticle.getStructureId());
2362                            article.setTemplateId(oldArticle.getTemplateId());
2363                            article.setLayoutUuid(oldArticle.getLayoutUuid());
2364                            article.setDisplayDate(oldArticle.getDisplayDate());
2365                            article.setExpirationDate(oldArticle.getExpirationDate());
2366                            article.setReviewDate(oldArticle.getReviewDate());
2367                            article.setIndexable(oldArticle.getIndexable());
2368                            article.setSmallImage(oldArticle.getSmallImage());
2369                            article.setSmallImageId(oldArticle.getSmallImageId());
2370    
2371                            if (article.getSmallImageId() == 0) {
2372                                    article.setSmallImageId(counterLocalService.increment());
2373                            }
2374    
2375                            article.setSmallImageURL(oldArticle.getSmallImageURL());
2376    
2377                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
2378                            article.setStatusDate(new Date());
2379                    }
2380                    else {
2381                            article = oldArticle;
2382                    }
2383    
2384                    Map<Locale, String> titleMap = article.getTitleMap();
2385    
2386                    titleMap.put(locale, title);
2387    
2388                    article.setTitleMap(titleMap);
2389    
2390                    Map<Locale, String> descriptionMap = article.getDescriptionMap();
2391    
2392                    descriptionMap.put(locale, description);
2393    
2394                    article.setDescriptionMap(descriptionMap);
2395    
2396                    content = format(
2397                            user, groupId, articleId, article.getVersion(),
2398                            !oldArticle.isDraft(), content, oldArticle.getStructureId(),
2399                            images);
2400    
2401                    article.setContent(content);
2402    
2403                    journalArticlePersistence.update(article);
2404    
2405                    return article;
2406            }
2407    
2408            public void updateAsset(
2409                            long userId, JournalArticle article, long[] assetCategoryIds,
2410                            String[] assetTagNames, long[] assetLinkEntryIds)
2411                    throws PortalException, SystemException {
2412    
2413                    boolean visible = article.isApproved();
2414    
2415                    if (article.getClassNameId() !=
2416                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2417    
2418                            visible = false;
2419                    }
2420    
2421                    boolean addDraftAssetEntry = false;
2422    
2423                    if (!article.isApproved() &&
2424                            (article.getVersion() != JournalArticleConstants.VERSION_DEFAULT)) {
2425    
2426                            int approvedArticlesCount = journalArticlePersistence.countByG_A_ST(
2427                                    article.getGroupId(), article.getArticleId(),
2428                                    JournalArticleConstants.ASSET_ENTRY_CREATION_STATUSES);
2429    
2430                            if (approvedArticlesCount > 0) {
2431                                    addDraftAssetEntry = true;
2432                            }
2433                    }
2434    
2435                    AssetEntry assetEntry = null;
2436    
2437                    if (addDraftAssetEntry) {
2438                            assetEntry = assetEntryLocalService.updateEntry(
2439                                    userId, article.getGroupId(), article.getCreateDate(),
2440                                    article.getModifiedDate(), JournalArticle.class.getName(),
2441                                    article.getPrimaryKey(), article.getUuid(),
2442                                    getClassTypeId(article), assetCategoryIds, assetTagNames, false,
2443                                    null, null, null, ContentTypes.TEXT_HTML, article.getTitle(),
2444                                    article.getDescription(), article.getDescription(), null,
2445                                    article.getLayoutUuid(), 0, 0, null, false);
2446                    }
2447                    else {
2448                            JournalArticleResource journalArticleResource =
2449                                    journalArticleResourceLocalService.getArticleResource(
2450                                            article.getResourcePrimKey());
2451    
2452                            assetEntry = assetEntryLocalService.updateEntry(
2453                                    userId, article.getGroupId(), article.getCreateDate(),
2454                                    article.getModifiedDate(), JournalArticle.class.getName(),
2455                                    journalArticleResource.getResourcePrimKey(),
2456                                    journalArticleResource.getUuid(), getClassTypeId(article),
2457                                    assetCategoryIds, assetTagNames, visible, null, null, null,
2458                                    ContentTypes.TEXT_HTML, article.getTitle(),
2459                                    article.getDescription(), article.getDescription(), null,
2460                                    article.getLayoutUuid(), 0, 0, null, false);
2461                    }
2462    
2463                    assetLinkLocalService.updateLinks(
2464                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
2465                            AssetLinkConstants.TYPE_RELATED);
2466            }
2467    
2468            public JournalArticle updateContent(
2469                            long groupId, String articleId, double version, String content)
2470                    throws PortalException, SystemException {
2471    
2472                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2473                            groupId, articleId, version);
2474    
2475                    article.setContent(content);
2476    
2477                    journalArticlePersistence.update(article);
2478    
2479                    return article;
2480            }
2481    
2482            public JournalArticle updateStatus(
2483                            long userId, JournalArticle article, int status, String articleURL,
2484                            ServiceContext serviceContext)
2485                    throws PortalException, SystemException {
2486    
2487                    // Article
2488    
2489                    User user = userPersistence.findByPrimaryKey(userId);
2490                    Date now = new Date();
2491    
2492                    int oldStatus = article.getStatus();
2493    
2494                    article.setModifiedDate(serviceContext.getModifiedDate(now));
2495    
2496                    boolean neverExpire = false;
2497    
2498                    if (status == WorkflowConstants.STATUS_APPROVED) {
2499                            Date expirationDate = article.getExpirationDate();
2500    
2501                            if ((expirationDate != null) && expirationDate.before(now)) {
2502                                    neverExpire = true;
2503    
2504                                    article.setExpirationDate(null);
2505                            }
2506                    }
2507    
2508                    if (status == WorkflowConstants.STATUS_EXPIRED) {
2509                            article.setExpirationDate(now);
2510                    }
2511    
2512                    article.setStatus(status);
2513                    article.setStatusByUserId(user.getUserId());
2514                    article.setStatusByUserName(user.getFullName());
2515                    article.setStatusDate(serviceContext.getModifiedDate(now));
2516    
2517                    journalArticlePersistence.update(article);
2518    
2519                    if (hasModifiedLatestApprovedVersion(
2520                                    article.getGroupId(), article.getArticleId(),
2521                                    article.getVersion())) {
2522    
2523                            if (status == WorkflowConstants.STATUS_APPROVED) {
2524                                    updateUrlTitles(
2525                                            article.getGroupId(), article.getArticleId(),
2526                                            article.getUrlTitle());
2527    
2528                                    // Asset
2529    
2530                                    if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2531                                            (article.getVersion() !=
2532                                                    JournalArticleConstants.VERSION_DEFAULT)) {
2533    
2534                                            AssetEntry draftAssetEntry = null;
2535    
2536                                            try {
2537                                                    draftAssetEntry = assetEntryLocalService.getEntry(
2538                                                            JournalArticle.class.getName(),
2539                                                            article.getPrimaryKey());
2540    
2541                                                    long[] assetCategoryIds =
2542                                                            draftAssetEntry.getCategoryIds();
2543                                                    String[] assetTagNames = draftAssetEntry.getTagNames();
2544    
2545                                                    List<AssetLink> assetLinks =
2546                                                            assetLinkLocalService.getDirectLinks(
2547                                                                    draftAssetEntry.getEntryId(),
2548                                                                    AssetLinkConstants.TYPE_RELATED);
2549    
2550                                                    long[] assetLinkEntryIds = StringUtil.split(
2551                                                            ListUtil.toString(
2552                                                                    assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2553    
2554                                                    AssetEntry assetEntry =
2555                                                            assetEntryLocalService.updateEntry(
2556                                                                    userId, article.getGroupId(),
2557                                                                    article.getCreateDate(),
2558                                                                    article.getModifiedDate(),
2559                                                                    JournalArticle.class.getName(),
2560                                                                    article.getResourcePrimKey(), article.getUuid(),
2561                                                                    getClassTypeId(article), assetCategoryIds,
2562                                                                    assetTagNames, false, null, null, null,
2563                                                                    ContentTypes.TEXT_HTML, article.getTitle(),
2564                                                                    article.getDescription(),
2565                                                                    article.getDescription(), null,
2566                                                                    article.getLayoutUuid(), 0, 0, null, false);
2567    
2568                                                    assetLinkLocalService.updateLinks(
2569                                                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
2570                                                            AssetLinkConstants.TYPE_RELATED);
2571    
2572                                                    assetEntryLocalService.deleteEntry(
2573                                                            JournalArticle.class.getName(),
2574                                                            article.getPrimaryKey());
2575                                            }
2576                                            catch (NoSuchEntryException nsee) {
2577                                            }
2578                                    }
2579    
2580                                    if (article.getClassNameId() ==
2581                                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2582    
2583                                            // Get the earliest display date and latest expiration date
2584                                            // among all article versions
2585    
2586                                            Date[] dateInterval = getDateInterval(
2587                                                    article.getGroupId(), article.getArticleId(),
2588                                                    article.getDisplayDate(), article.getExpirationDate());
2589    
2590                                            Date displayDate = dateInterval[0];
2591                                            Date expirationDate = dateInterval[1];
2592    
2593                                            if (neverExpire) {
2594                                                    expirationDate = null;
2595                                            }
2596    
2597                                            assetEntryLocalService.updateEntry(
2598                                                    JournalArticle.class.getName(),
2599                                                    article.getResourcePrimKey(), displayDate,
2600                                                    expirationDate, true);
2601                                    }
2602    
2603                                    // Indexer
2604    
2605                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2606                                            JournalArticle.class);
2607    
2608                                    indexer.reindex(article);
2609                            }
2610                            else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
2611                                    updatePreviousApprovedArticle(article);
2612                            }
2613                    }
2614    
2615                    if (article.getClassNameId() ==
2616                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
2617    
2618                            // Email
2619    
2620                            if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
2621                                    ((status == WorkflowConstants.STATUS_APPROVED) ||
2622                                     (status == WorkflowConstants.STATUS_DENIED))) {
2623    
2624                                    String msg = "granted";
2625    
2626                                    if (status == WorkflowConstants.STATUS_DENIED) {
2627                                            msg = "denied";
2628                                    }
2629    
2630                                    try {
2631                                            PortletPreferences preferences =
2632                                                    ServiceContextUtil.getPortletPreferences(
2633                                                            serviceContext);
2634    
2635                                            sendEmail(
2636                                                    article, articleURL, preferences, msg, serviceContext);
2637                                    }
2638                                    catch (Exception e) {
2639                                            _log.error(
2640                                                    "Unable to send email to notify the change of status " +
2641                                                            " to " + msg + " for article " + article.getId() +
2642                                                                    ": " + e.getMessage());
2643                                    }
2644                            }
2645    
2646                            // Subscriptions
2647    
2648                            notifySubscribers(article, serviceContext);
2649                    }
2650    
2651                    return article;
2652            }
2653    
2654            public JournalArticle updateStatus(
2655                            long userId, long classPK, int status,
2656                            ServiceContext serviceContext)
2657                    throws PortalException, SystemException {
2658    
2659                    JournalArticle article = getArticle(classPK);
2660    
2661                    return updateStatus(userId, article, status, null, serviceContext);
2662            }
2663    
2664            public JournalArticle updateStatus(
2665                            long userId, long groupId, String articleId, double version,
2666                            int status, String articleURL, ServiceContext serviceContext)
2667                    throws PortalException, SystemException {
2668    
2669                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2670                            groupId, articleId, version);
2671    
2672                    return updateStatus(
2673                            userId, article, status, articleURL, serviceContext);
2674            }
2675    
2676            public void updateTemplateId(
2677                            long groupId, long classNameId, String oldTemplateId,
2678                            String newTemplateId)
2679                    throws SystemException {
2680    
2681                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_T(
2682                            groupId, classNameId, oldTemplateId);
2683    
2684                    for (JournalArticle article : articles) {
2685                            article.setTemplateId(newTemplateId);
2686    
2687                            journalArticlePersistence.update(article);
2688                    }
2689            }
2690    
2691            protected void checkStructure(Document contentDoc, Element root)
2692                    throws PortalException {
2693    
2694                    for (Element el : root.elements()) {
2695                            checkStructureField(el, contentDoc);
2696    
2697                            checkStructure(contentDoc, el);
2698                    }
2699            }
2700    
2701            protected void checkStructure(JournalArticle article)
2702                    throws PortalException, SystemException {
2703    
2704                    Group companyGroup = groupLocalService.getCompanyGroup(
2705                            article.getCompanyId());
2706    
2707                    DDMStructure structure = null;
2708    
2709                    try {
2710                            structure = ddmStructurePersistence.findByG_S(
2711                                    article.getGroupId(), article.getStructureId());
2712                    }
2713                    catch (NoSuchStructureException nsse) {
2714                            structure = ddmStructurePersistence.findByG_S(
2715                                    companyGroup.getGroupId(), article.getStructureId());
2716                    }
2717    
2718                    String content = GetterUtil.getString(article.getContent());
2719    
2720                    try {
2721                            Document contentDocument = SAXReaderUtil.read(content);
2722                            Document xsdDocument = SAXReaderUtil.read(structure.getXsd());
2723    
2724                            checkStructure(contentDocument, xsdDocument.getRootElement());
2725                    }
2726                    catch (DocumentException de) {
2727                            throw new SystemException(de);
2728                    }
2729                    catch (StructureXsdException sxsde) {
2730                            long groupId = article.getGroupId();
2731                            String articleId = article.getArticleId();
2732                            double version = article.getVersion();
2733    
2734                            if (_log.isWarnEnabled()) {
2735                                    _log.warn(
2736                                            "Article {groupId=" + groupId + ", articleId=" +
2737                                                    articleId + ", version=" + version +
2738                                                            "} has content that does not match its " +
2739                                                                    "structure: " + sxsde.getMessage());
2740                            }
2741                    }
2742            }
2743    
2744            protected void checkStructureField(Element el, Document contentDoc)
2745                    throws PortalException {
2746    
2747                    StringBuilder elPath = new StringBuilder();
2748    
2749                    elPath.append(el.attributeValue("name"));
2750    
2751                    Element elParent = el.getParent();
2752    
2753                    for (;;) {
2754                            if ((elParent == null) || elParent.getName().equals("root")) {
2755                                    break;
2756                            }
2757    
2758                            elPath.insert(
2759                                    0, elParent.attributeValue("name") + StringPool.COMMA);
2760    
2761                            elParent = elParent.getParent();
2762                    }
2763    
2764                    String[] elPathNames = StringUtil.split(elPath.toString());
2765    
2766                    Element contentEl = contentDoc.getRootElement();
2767    
2768                    for (String _elPathName : elPathNames) {
2769                            boolean foundEl = false;
2770    
2771                            for (Element tempEl : contentEl.elements()) {
2772                                    if (_elPathName.equals(
2773                                                    tempEl.attributeValue("name", StringPool.BLANK))) {
2774    
2775                                            contentEl = tempEl;
2776                                            foundEl = true;
2777    
2778                                            break;
2779                                    }
2780                            }
2781    
2782                            if (!foundEl) {
2783                                    String elType = contentEl.attributeValue(
2784                                            "type", StringPool.BLANK);
2785    
2786                                    if (!elType.equals("list") && !elType.equals("multi-list")) {
2787                                            throw new StructureXsdException(elPath.toString());
2788                                    }
2789    
2790                                    break;
2791                            }
2792                    }
2793            }
2794    
2795            protected void copyArticleImages(
2796                            JournalArticle oldArticle, JournalArticle newArticle)
2797                    throws Exception {
2798    
2799                    Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
2800    
2801                    XPath xPathSelector = SAXReaderUtil.createXPath(
2802                            "//dynamic-element[@type='image']");
2803    
2804                    List<Node> imageNodes = xPathSelector.selectNodes(contentDoc);
2805    
2806                    for (Node imageNode : imageNodes) {
2807                            Element imageEl = (Element)imageNode;
2808    
2809                            String instanceId = imageEl.attributeValue("instance-id");
2810                            String name = imageEl.attributeValue("name");
2811    
2812                            List<Element> dynamicContentEls = imageEl.elements(
2813                                    "dynamic-content");
2814    
2815                            for (Element dynamicContentEl : dynamicContentEls) {
2816                                    long imageId = GetterUtil.getLong(
2817                                            dynamicContentEl.attributeValue("id"));
2818                                    String languageId = dynamicContentEl.attributeValue(
2819                                            "language-id");
2820    
2821                                    Image oldImage = null;
2822    
2823                                    try {
2824                                            oldImage = imageLocalService.getImage(imageId);
2825                                    }
2826                                    catch (NoSuchImageException nsie) {
2827                                            continue;
2828                                    }
2829    
2830                                    imageId = journalArticleImageLocalService.getArticleImageId(
2831                                            newArticle.getGroupId(), newArticle.getArticleId(),
2832                                            newArticle.getVersion(), instanceId, name, languageId);
2833    
2834                                    imageLocalService.updateImage(imageId, oldImage.getTextObj());
2835    
2836                                    String elContent =
2837                                            "/image/journal/article?img_id=" + imageId + "&t=" +
2838                                                    WebServerServletTokenUtil.getToken(imageId);
2839    
2840                                    dynamicContentEl.setText(elContent);
2841                                    dynamicContentEl.addAttribute("id", String.valueOf(imageId));
2842                            }
2843                    }
2844    
2845                    newArticle.setContent(contentDoc.formattedString());
2846            }
2847    
2848            protected void format(
2849                            User user, long groupId, String articleId, double version,
2850                            boolean incrementVersion, Element root, Map<String, byte[]> images)
2851                    throws PortalException, SystemException {
2852    
2853                    for (Element element : root.elements()) {
2854                            String elInstanceId = element.attributeValue(
2855                                    "instance-id", StringPool.BLANK);
2856                            String elName = element.attributeValue("name", StringPool.BLANK);
2857                            String elType = element.attributeValue("type", StringPool.BLANK);
2858    
2859                            if (elType.equals("image")) {
2860                                    formatImage(
2861                                            groupId, articleId, version, incrementVersion, element,
2862                                            elInstanceId, elName, images);
2863                            }
2864                            else if (elType.equals("text_area") || elType.equals("text") ||
2865                                             elType.equals("text_box")) {
2866    
2867                                    List<Element> dynamicContentElements = element.elements(
2868                                            "dynamic-content");
2869    
2870                                    for (Element dynamicContentElement : dynamicContentElements) {
2871                                            String dynamicContent = dynamicContentElement.getText();
2872    
2873                                            if (Validator.isNotNull(dynamicContent)) {
2874                                                    dynamicContent = SanitizerUtil.sanitize(
2875                                                            user.getCompanyId(), groupId, user.getUserId(),
2876                                                            JournalArticle.class.getName(), 0,
2877                                                            ContentTypes.TEXT_HTML, dynamicContent);
2878    
2879                                                    dynamicContentElement.clearContent();
2880    
2881                                                    dynamicContentElement.addCDATA(dynamicContent);
2882                                            }
2883                                    }
2884                            }
2885    
2886                            format(
2887                                    user, groupId, articleId, version, incrementVersion, element,
2888                                    images);
2889                    }
2890            }
2891    
2892            protected String format(
2893                            User user, long groupId, String articleId, double version,
2894                            boolean incrementVersion, String content, String structureId,
2895                            Map<String, byte[]> images)
2896                    throws PortalException, SystemException {
2897    
2898                    Document document = null;
2899    
2900                    try {
2901                            document = SAXReaderUtil.read(content);
2902    
2903                            Element rootElement = document.getRootElement();
2904    
2905                            if (Validator.isNotNull(structureId)) {
2906                                    format(
2907                                            user, groupId, articleId, version, incrementVersion,
2908                                            rootElement, images);
2909                            }
2910                            else {
2911                                    List<Element> staticContentElements = rootElement.elements(
2912                                            "static-content");
2913    
2914                                    for (Element staticContentElement : staticContentElements) {
2915                                            String staticContent = staticContentElement.getText();
2916    
2917                                            staticContent = SanitizerUtil.sanitize(
2918                                                    user.getCompanyId(), groupId, user.getUserId(),
2919                                                    JournalArticle.class.getName(), 0,
2920                                                    ContentTypes.TEXT_HTML, staticContent);
2921    
2922                                            staticContentElement.clearContent();
2923    
2924                                            staticContentElement.addCDATA(staticContent);
2925                                    }
2926                            }
2927    
2928                            content = DDMXMLUtil.formatXML(document);
2929                    }
2930                    catch (DocumentException de) {
2931                            _log.error(de, de);
2932                    }
2933    
2934                    content = HtmlUtil.replaceMsWordCharacters(content);
2935    
2936                    return content;
2937            }
2938    
2939            protected void formatImage(
2940                            long groupId, String articleId, double version,
2941                            boolean incrementVersion, Element el, String elInstanceId,
2942                            String elName, Map<String, byte[]> images)
2943                    throws PortalException, SystemException {
2944    
2945                    List<Element> imageContents = el.elements("dynamic-content");
2946    
2947                    for (Element dynamicContent : imageContents) {
2948                            String elLanguage = dynamicContent.attributeValue(
2949                                    "language-id", StringPool.BLANK);
2950    
2951                            if (!elLanguage.equals(StringPool.BLANK)) {
2952                                    elLanguage = "_" + elLanguage;
2953                            }
2954    
2955                            long imageId = journalArticleImageLocalService.getArticleImageId(
2956                                    groupId, articleId, version, elInstanceId, elName, elLanguage);
2957    
2958                            double oldVersion = MathUtil.format(version - 0.1, 1, 1);
2959    
2960                            long oldImageId = 0;
2961    
2962                            if ((oldVersion >= 1) && incrementVersion) {
2963                                    oldImageId = journalArticleImageLocalService.getArticleImageId(
2964                                            groupId, articleId, oldVersion, elInstanceId, elName,
2965                                            elLanguage);
2966                            }
2967    
2968                            String elContent =
2969                                    "/image/journal/article?img_id=" + imageId + "&t=" +
2970                                            WebServerServletTokenUtil.getToken(imageId);
2971    
2972                            if (dynamicContent.getText().equals("delete")) {
2973                                    dynamicContent.setText(StringPool.BLANK);
2974    
2975                                    imageLocalService.deleteImage(imageId);
2976    
2977                                    String defaultElLanguage = "";
2978    
2979                                    if (!Validator.isNotNull(elLanguage)) {
2980                                            defaultElLanguage =
2981                                                    "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2982                                    }
2983    
2984                                    long defaultImageId =
2985                                            journalArticleImageLocalService.getArticleImageId(
2986                                                    groupId, articleId, version, elInstanceId, elName,
2987                                                    defaultElLanguage);
2988    
2989                                    imageLocalService.deleteImage(defaultImageId);
2990    
2991                                    continue;
2992                            }
2993    
2994                            byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
2995    
2996                            if ((bytes != null) && (bytes.length > 0)) {
2997                                    dynamicContent.setText(elContent);
2998                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2999    
3000                                    imageLocalService.updateImage(imageId, bytes);
3001    
3002                                    continue;
3003                            }
3004    
3005                            if ((version > JournalArticleConstants.VERSION_DEFAULT) &&
3006                                    incrementVersion) {
3007    
3008                                    Image oldImage = null;
3009    
3010                                    if (oldImageId > 0) {
3011                                            oldImage = imageLocalService.getImage(oldImageId);
3012                                    }
3013    
3014                                    if (oldImage != null) {
3015                                            dynamicContent.setText(elContent);
3016                                            dynamicContent.addAttribute("id", String.valueOf(imageId));
3017    
3018                                            bytes = oldImage.getTextObj();
3019    
3020                                            imageLocalService.updateImage(imageId, bytes);
3021                                    }
3022    
3023                                    continue;
3024                            }
3025    
3026                            Image image = imageLocalService.getImage(imageId);
3027    
3028                            if (image != null) {
3029                                    dynamicContent.setText(elContent);
3030                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
3031    
3032                                    continue;
3033                            }
3034    
3035                            long contentImageId = GetterUtil.getLong(
3036                                    HttpUtil.getParameter(dynamicContent.getText(), "img_id"));
3037    
3038                            if (contentImageId <= 0) {
3039                                    contentImageId = GetterUtil.getLong(
3040                                            HttpUtil.getParameter(
3041                                                    dynamicContent.getText(), "img_id", false));
3042                            }
3043    
3044                            if (contentImageId > 0) {
3045                                    image = imageLocalService.getImage(contentImageId);
3046    
3047                                    if (image != null) {
3048                                            dynamicContent.addAttribute(
3049                                                    "id", String.valueOf(contentImageId));
3050    
3051                                            continue;
3052                                    }
3053                            }
3054    
3055                            String defaultElLanguage = "";
3056    
3057                            if (!Validator.isNotNull(elLanguage)) {
3058                                    defaultElLanguage =
3059                                            "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
3060                            }
3061    
3062                            long defaultImageId =
3063                                    journalArticleImageLocalService.getArticleImageId(
3064                                            groupId, articleId, version, elInstanceId, elName,
3065                                            defaultElLanguage);
3066    
3067                            Image defaultImage = imageLocalService.getImage(defaultImageId);
3068    
3069                            if (defaultImage != null) {
3070                                    dynamicContent.setText(elContent);
3071                                    dynamicContent.addAttribute(
3072                                            "id", String.valueOf(defaultImageId));
3073    
3074                                    bytes = defaultImage.getTextObj();
3075    
3076                                    imageLocalService.updateImage(defaultImageId, bytes);
3077    
3078                                    continue;
3079                            }
3080    
3081                            if (Validator.isNotNull(elLanguage)) {
3082                                    dynamicContent.setText(StringPool.BLANK);
3083                            }
3084                    }
3085            }
3086    
3087            protected long getClassTypeId(JournalArticle article) {
3088                    long classTypeId = 0;
3089    
3090                    try {
3091                            DDMStructure ddmStructure = ddmStructurePersistence.fetchByG_S(
3092                                    article.getGroupId(), article.getStructureId());
3093    
3094                            if (ddmStructure == null) {
3095                                    Group companyGroup = groupLocalService.getCompanyGroup(
3096                                            article.getCompanyId());
3097    
3098                                    ddmStructure = ddmStructurePersistence.fetchByG_S(
3099                                            companyGroup.getGroupId(), article.getStructureId());
3100                            }
3101    
3102                            if (ddmStructure != null) {
3103                                    classTypeId = ddmStructure.getStructureId();
3104                            }
3105                    }
3106                    catch (Exception e) {
3107                            _log.error(e, e);
3108                    }
3109    
3110                    return classTypeId;
3111            }
3112    
3113            protected Date[] getDateInterval(
3114                            long groupId, String articleId, Date earliestDisplayDate,
3115                            Date latestExpirationDate)
3116                    throws SystemException {
3117    
3118                    Date[] dateInterval = new Date[2];
3119    
3120                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
3121                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
3122    
3123                    boolean expiringArticle = true;
3124    
3125                    if (latestExpirationDate == null) {
3126                            expiringArticle = false;
3127                    }
3128    
3129                    for (JournalArticle article : articles) {
3130                            if ((earliestDisplayDate == null) ||
3131                                    ((article.getDisplayDate() != null) &&
3132                                     earliestDisplayDate.after(article.getDisplayDate()))) {
3133    
3134                                    earliestDisplayDate = article.getDisplayDate();
3135                            }
3136    
3137                            if (expiringArticle &&
3138                                    ((latestExpirationDate == null) ||
3139                                     ((article.getExpirationDate() != null) &&
3140                                      latestExpirationDate.before(article.getExpirationDate())))) {
3141    
3142                                    latestExpirationDate = article.getExpirationDate();
3143                            }
3144    
3145                            if (expiringArticle && (article.getExpirationDate() == null) &&
3146                                    (latestExpirationDate != null)) {
3147    
3148                                    expiringArticle = false;
3149                            }
3150                    }
3151    
3152                    dateInterval[0] = earliestDisplayDate;
3153                    dateInterval[1] = latestExpirationDate;
3154    
3155                    return dateInterval;
3156            }
3157    
3158            protected String getUniqueUrlTitle(
3159                            long id, long groupId, String articleId, String title)
3160                    throws PortalException, SystemException {
3161    
3162                    String urlTitle = JournalUtil.getUrlTitle(id, title);
3163    
3164                    for (int i = 1;; i++) {
3165                            JournalArticle article = null;
3166    
3167                            try {
3168                                    article = getArticleByUrlTitle(groupId, urlTitle);
3169                            }
3170                            catch (NoSuchArticleException nsae) {
3171                            }
3172    
3173                            if ((article == null) || articleId.equals(article.getArticleId())) {
3174                                    break;
3175                            }
3176                            else {
3177                                    String suffix = StringPool.DASH + i;
3178    
3179                                    String prefix = urlTitle;
3180    
3181                                    if (urlTitle.length() > suffix.length()) {
3182                                            prefix = urlTitle.substring(
3183                                                    0, urlTitle.length() - suffix.length());
3184                                    }
3185    
3186                                    urlTitle = prefix + suffix;
3187                            }
3188                    }
3189    
3190                    return urlTitle;
3191            }
3192    
3193            protected String getUniqueUrlTitle(
3194                            long id, String articleId, String title, String oldUrlTitle,
3195                            ServiceContext serviceContext)
3196                    throws PortalException, SystemException {
3197    
3198                    String serviceContextUrlTitle = ParamUtil.getString(
3199                            serviceContext, "urlTitle");
3200    
3201                    String urlTitle = null;
3202    
3203                    if (Validator.isNotNull(serviceContextUrlTitle)) {
3204                            urlTitle = JournalUtil.getUrlTitle(id, serviceContextUrlTitle);
3205                    }
3206                    else if (Validator.isNotNull(oldUrlTitle)) {
3207                            return oldUrlTitle;
3208                    }
3209                    else {
3210                            urlTitle = getUniqueUrlTitle(
3211                                    id, serviceContext.getScopeGroupId(), articleId, title);
3212                    }
3213    
3214                    JournalArticle urlTitleArticle = null;
3215    
3216                    try {
3217                            urlTitleArticle = getArticleByUrlTitle(
3218                                    serviceContext.getScopeGroupId(), urlTitle);
3219                    }
3220                    catch (NoSuchArticleException nsae) {
3221                    }
3222    
3223                    if ((urlTitleArticle != null) &&
3224                            !Validator.equals(
3225                                    urlTitleArticle.getArticleId(), articleId)) {
3226    
3227                            urlTitle = getUniqueUrlTitle(
3228                                    id, serviceContext.getScopeGroupId(), articleId, urlTitle);
3229                    }
3230    
3231                    return urlTitle;
3232            }
3233    
3234            protected boolean hasModifiedLatestApprovedVersion(
3235                            long groupId, String articleId, double version)
3236                    throws PortalException, SystemException {
3237    
3238                    double latestApprovedVersion;
3239    
3240                    try {
3241                            latestApprovedVersion = getLatestVersion(
3242                                    groupId, articleId, WorkflowConstants.STATUS_APPROVED);
3243    
3244                            if (version >= latestApprovedVersion) {
3245                                    return true;
3246                            }
3247                            else {
3248                                    return false;
3249                            }
3250                    }
3251                    catch (NoSuchArticleException nsae) {
3252                            return true;
3253                    }
3254            }
3255    
3256            protected void notifySubscribers(
3257                            JournalArticle article, ServiceContext serviceContext)
3258                    throws PortalException, SystemException {
3259    
3260                    if (!article.isApproved()) {
3261                            return;
3262                    }
3263    
3264                    String articleURL = PortalUtil.getControlPanelFullURL(
3265                            serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
3266    
3267                    if (Validator.isNull(articleURL)) {
3268                            return;
3269                    }
3270    
3271                    PortletPreferences preferences =
3272                            ServiceContextUtil.getPortletPreferences(serviceContext);
3273    
3274                    if (preferences == null) {
3275                            long ownerId = article.getGroupId();
3276                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
3277                            long plid = PortletKeys.PREFS_PLID_SHARED;
3278                            String portletId = PortletKeys.JOURNAL;
3279                            String defaultPreferences = null;
3280    
3281                            preferences = portletPreferencesLocalService.getPreferences(
3282                                    article.getCompanyId(), ownerId, ownerType, plid, portletId,
3283                                    defaultPreferences);
3284                    }
3285    
3286                    if ((article.getVersion() == 1.0) &&
3287                            JournalUtil.getEmailArticleAddedEnabled(preferences)) {
3288                    }
3289                    else if ((article.getVersion() != 1.0) &&
3290                                     JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
3291                    }
3292                    else {
3293                            return;
3294                    }
3295    
3296                    String fromName = JournalUtil.getEmailFromName(
3297                            preferences, article.getCompanyId());
3298                    String fromAddress = JournalUtil.getEmailFromAddress(
3299                            preferences, article.getCompanyId());
3300    
3301                    String subject = null;
3302                    String body = null;
3303    
3304                    if (article.getVersion() == 1.0) {
3305                            subject = JournalUtil.getEmailArticleAddedSubject(preferences);
3306                            body = JournalUtil.getEmailArticleAddedBody(preferences);
3307                    }
3308                    else {
3309                            subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
3310                            body = JournalUtil.getEmailArticleUpdatedBody(preferences);
3311                    }
3312    
3313                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3314    
3315                    subscriptionSender.setBody(body);
3316                    subscriptionSender.setCompanyId(article.getCompanyId());
3317                    subscriptionSender.setContextAttributes(
3318                            "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3319                            article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
3320                            articleURL, "[$ARTICLE_VERSION$]", article.getVersion());
3321                    subscriptionSender.setContextUserPrefix("ARTICLE");
3322                    subscriptionSender.setFrom(fromAddress, fromName);
3323                    subscriptionSender.setHtmlFormat(true);
3324                    subscriptionSender.setMailId("journal_article", article.getId());
3325                    subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3326                    subscriptionSender.setReplyToAddress(fromAddress);
3327                    subscriptionSender.setScopeGroupId(article.getGroupId());
3328                    subscriptionSender.setServiceContext(serviceContext);
3329                    subscriptionSender.setSubject(subject);
3330                    subscriptionSender.setUserId(article.getUserId());
3331    
3332                    subscriptionSender.addPersistedSubscribers(
3333                            JournalArticle.class.getName(), article.getGroupId());
3334    
3335                    subscriptionSender.flushNotificationsAsync();
3336            }
3337    
3338            protected void saveImages(
3339                            boolean smallImage, long smallImageId, File smallImageFile,
3340                            byte[] smallImageBytes)
3341                    throws PortalException, SystemException {
3342    
3343                    if (smallImage) {
3344                            if ((smallImageFile != null) && (smallImageBytes != null)) {
3345                                    imageLocalService.updateImage(smallImageId, smallImageBytes);
3346                            }
3347                    }
3348                    else {
3349                            imageLocalService.deleteImage(smallImageId);
3350                    }
3351            }
3352    
3353            protected void sendEmail(
3354                            JournalArticle article, String articleURL,
3355                            PortletPreferences preferences, String emailType,
3356                            ServiceContext serviceContext)
3357                    throws PortalException, SystemException {
3358    
3359                    if (preferences == null) {
3360                            return;
3361                    }
3362                    else if (emailType.equals("denied") &&
3363                                     JournalUtil.getEmailArticleApprovalDeniedEnabled(
3364                                             preferences)) {
3365                    }
3366                    else if (emailType.equals("granted") &&
3367                                     JournalUtil.getEmailArticleApprovalGrantedEnabled(
3368                                             preferences)) {
3369                    }
3370                    else if (emailType.equals("requested") &&
3371                                     JournalUtil.getEmailArticleApprovalRequestedEnabled(
3372                                             preferences)) {
3373                    }
3374                    else if (emailType.equals("review") &&
3375                                     JournalUtil.getEmailArticleReviewEnabled(preferences)) {
3376                    }
3377                    else {
3378                            return;
3379                    }
3380    
3381                    Company company = companyPersistence.findByPrimaryKey(
3382                            article.getCompanyId());
3383    
3384                    User user = userPersistence.findByPrimaryKey(article.getUserId());
3385    
3386                    articleURL +=
3387                            "&groupId=" + article.getGroupId() + "&articleId=" +
3388                                    article.getArticleId() + "&version=" + article.getVersion();
3389    
3390                    String fromName = JournalUtil.getEmailFromName(
3391                            preferences, article.getCompanyId());
3392                    String fromAddress = JournalUtil.getEmailFromAddress(
3393                            preferences, article.getCompanyId());
3394    
3395                    String toName = user.getFullName();
3396                    String toAddress = user.getEmailAddress();
3397    
3398                    if (emailType.equals("requested") || emailType.equals("review")) {
3399                            String tempToName = fromName;
3400                            String tempToAddress = fromAddress;
3401    
3402                            fromName = toName;
3403                            fromAddress = toAddress;
3404    
3405                            toName = tempToName;
3406                            toAddress = tempToAddress;
3407                    }
3408    
3409                    String subject = null;
3410                    String body = null;
3411    
3412                    if (emailType.equals("denied")) {
3413                            subject = JournalUtil.getEmailArticleApprovalDeniedSubject(
3414                                    preferences);
3415                            body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
3416                    }
3417                    else if (emailType.equals("granted")) {
3418                            subject = JournalUtil.getEmailArticleApprovalGrantedSubject(
3419                                    preferences);
3420                            body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
3421                    }
3422                    else if (emailType.equals("requested")) {
3423                            subject = JournalUtil.getEmailArticleApprovalRequestedSubject(
3424                                    preferences);
3425                            body = JournalUtil.getEmailArticleApprovalRequestedBody(
3426                                    preferences);
3427                    }
3428                    else if (emailType.equals("review")) {
3429                            subject = JournalUtil.getEmailArticleReviewSubject(preferences);
3430                            body = JournalUtil.getEmailArticleReviewBody(preferences);
3431                    }
3432    
3433                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3434    
3435                    subscriptionSender.setBody(body);
3436                    subscriptionSender.setCompanyId(company.getCompanyId());
3437                    subscriptionSender.setContextAttributes(
3438                            "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3439                            article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
3440                            articleURL, "[$ARTICLE_USER_NAME$]", article.getUserName(),
3441                            "[$ARTICLE_VERSION$]", article.getVersion());
3442                    subscriptionSender.setContextUserPrefix("ARTICLE");
3443                    subscriptionSender.setFrom(fromAddress, fromName);
3444                    subscriptionSender.setHtmlFormat(true);
3445                    subscriptionSender.setMailId("journal_article", article.getId());
3446                    subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3447                    subscriptionSender.setScopeGroupId(article.getGroupId());
3448                    subscriptionSender.setServiceContext(serviceContext);
3449                    subscriptionSender.setSubject(subject);
3450                    subscriptionSender.setUserId(article.getUserId());
3451    
3452                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
3453    
3454                    subscriptionSender.flushNotificationsAsync();
3455            }
3456    
3457            protected void updatePreviousApprovedArticle(JournalArticle article)
3458                    throws PortalException, SystemException {
3459    
3460                    List<JournalArticle> approvedArticles =
3461                            journalArticlePersistence.findByG_A_ST(
3462                                    article.getGroupId(), article.getArticleId(),
3463                                    WorkflowConstants.STATUS_APPROVED, 0, 2);
3464    
3465                    if (approvedArticles.isEmpty() ||
3466                            ((approvedArticles.size() == 1) &&
3467                             (article.getStatus() == WorkflowConstants.STATUS_APPROVED))) {
3468    
3469                            if (article.isIndexable()) {
3470                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3471                                            JournalArticle.class);
3472    
3473                                    indexer.delete(article);
3474                            }
3475    
3476                            assetEntryLocalService.updateVisible(
3477                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
3478                                    false);
3479                    }
3480                    else {
3481                            JournalArticle previousApprovedArticle = approvedArticles.get(0);
3482    
3483                            if (article.getStatus() == WorkflowConstants.STATUS_APPROVED) {
3484                                    previousApprovedArticle = approvedArticles.get(1);
3485                            }
3486    
3487                            Date[] dateInterval = getDateInterval(
3488                                    previousApprovedArticle.getGroupId(),
3489                                    previousApprovedArticle.getArticleId(),
3490                                    previousApprovedArticle.getDisplayDate(),
3491                                    previousApprovedArticle.getExpirationDate());
3492    
3493                            Date displayDate = dateInterval[0];
3494                            Date expirationDate = dateInterval[1];
3495    
3496                            AssetEntry assetEntry = assetEntryLocalService.updateEntry(
3497                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
3498                                    displayDate, expirationDate, true);
3499    
3500                            assetEntry.setModifiedDate(
3501                                    previousApprovedArticle.getModifiedDate());
3502    
3503                            assetEntryPersistence.update(assetEntry);
3504    
3505                            if (article.isIndexable()) {
3506                                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3507                                            JournalArticle.class);
3508    
3509                                    indexer.reindex(previousApprovedArticle);
3510                            }
3511                    }
3512            }
3513    
3514            protected void updateUrlTitles(
3515                            long groupId, String articleId, String urlTitle)
3516                    throws SystemException {
3517    
3518                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
3519                            groupId, articleId);
3520    
3521                    for (JournalArticle article : articles) {
3522                            if (!article.getUrlTitle().equals(urlTitle)) {
3523                                    article.setUrlTitle(urlTitle);
3524    
3525                                    journalArticlePersistence.update(article);
3526                            }
3527                    }
3528            }
3529    
3530            protected void validate(
3531                            long companyId, long groupId, long classNameId,
3532                            Map<Locale, String> titleMap, String content, String type,
3533                            String structureId, String templateId, Date expirationDate,
3534                            boolean smallImage, String smallImageURL, File smallImageFile,
3535                            byte[] smallImageBytes)
3536                    throws PortalException, SystemException {
3537    
3538                    Locale articleDefaultLocale = LocaleUtil.fromLanguageId(
3539                            LocalizationUtil.getDefaultLocale(content));
3540    
3541                    Locale[] availableLocales = LanguageUtil.getAvailableLocales();
3542    
3543                    if (!ArrayUtil.contains(availableLocales, articleDefaultLocale)) {
3544                            LocaleException le = new LocaleException();
3545    
3546                            Locale[] sourceAvailableLocales = {articleDefaultLocale};
3547    
3548                            le.setSourceAvailableLocales(sourceAvailableLocales);
3549                            le.setTargetAvailableLocales(availableLocales);
3550    
3551                            throw le;
3552                    }
3553    
3554                    if ((classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) &&
3555                            (titleMap.isEmpty() ||
3556                             Validator.isNull(titleMap.get(articleDefaultLocale)))) {
3557    
3558                            throw new ArticleTitleException();
3559                    }
3560                    else if (Validator.isNull(type)) {
3561                            throw new ArticleTypeException();
3562                    }
3563    
3564                    validateContent(content);
3565    
3566                    if (Validator.isNotNull(structureId)) {
3567                            Group companyGroup = groupLocalService.getCompanyGroup(companyId);
3568    
3569                            DDMStructure ddmStructure = null;
3570    
3571                            try {
3572                                    ddmStructure = ddmStructurePersistence.findByG_S(
3573                                            groupId, structureId);
3574                            }
3575                            catch (NoSuchStructureException nsse) {
3576                                    ddmStructure = ddmStructurePersistence.findByG_S(
3577                                            companyGroup.getGroupId(), structureId);
3578                            }
3579    
3580                            DDMTemplate ddmTemplate = null;
3581    
3582                            if (Validator.isNotNull(templateId)) {
3583                                    ddmTemplate = ddmTemplateService.getTemplate(
3584                                            groupId, templateId);
3585    
3586                                    if (ddmTemplate.getClassPK() != ddmStructure.getStructureId()) {
3587                                            throw new NoSuchTemplateException();
3588                                    }
3589                            }
3590                            else if (classNameId ==
3591                                                    JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
3592    
3593                                    throw new NoSuchTemplateException();
3594                            }
3595                    }
3596    
3597                    if ((expirationDate != null) && expirationDate.before(new Date()) &&
3598                            !ImportExportThreadLocal.isImportInProcess()) {
3599    
3600                            throw new ArticleExpirationDateException();
3601                    }
3602    
3603                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
3604                            PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
3605    
3606                    if (smallImage && Validator.isNull(smallImageURL) &&
3607                            (smallImageFile != null) && (smallImageBytes != null)) {
3608    
3609                            String smallImageName = smallImageFile.getName();
3610    
3611                            if (smallImageName != null) {
3612                                    boolean validSmallImageExtension = false;
3613    
3614                                    for (String _imageExtension : imageExtensions) {
3615                                            if (StringPool.STAR.equals(_imageExtension) ||
3616                                                    StringUtil.endsWith(smallImageName, _imageExtension)) {
3617    
3618                                                    validSmallImageExtension = true;
3619    
3620                                                    break;
3621                                            }
3622                                    }
3623    
3624                                    if (!validSmallImageExtension) {
3625                                            throw new ArticleSmallImageNameException(smallImageName);
3626                                    }
3627                            }
3628    
3629                            long smallImageMaxSize = PrefsPropsUtil.getLong(
3630                                    PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
3631    
3632                            if ((smallImageMaxSize > 0) &&
3633                                    ((smallImageBytes == null) ||
3634                                     (smallImageBytes.length > smallImageMaxSize))) {
3635    
3636                                    throw new ArticleSmallImageSizeException();
3637                            }
3638                    }
3639            }
3640    
3641            protected void validate(
3642                            long companyId, long groupId, long classNameId, String articleId,
3643                            boolean autoArticleId, double version, Map<Locale, String> titleMap,
3644                            String content, String type, String structureId, String templateId,
3645                            Date expirationDate, boolean smallImage, String smallImageURL,
3646                            File smallImageFile, byte[] smallImageBytes)
3647                    throws PortalException, SystemException {
3648    
3649                    if (!autoArticleId) {
3650                            validate(articleId);
3651                    }
3652    
3653                    JournalArticle article = journalArticlePersistence.fetchByG_A_V(
3654                            groupId, articleId, version);
3655    
3656                    if (article != null) {
3657                            throw new DuplicateArticleIdException();
3658                    }
3659    
3660                    validate(
3661                            companyId, groupId, classNameId, titleMap, content, type,
3662                            structureId, templateId, expirationDate, smallImage, smallImageURL,
3663                            smallImageFile, smallImageBytes);
3664            }
3665    
3666            protected void validate(String articleId) throws PortalException {
3667                    if (Validator.isNull(articleId) ||
3668                            (articleId.indexOf(CharPool.SPACE) != -1)) {
3669    
3670                            throw new ArticleIdException();
3671                    }
3672            }
3673    
3674            protected void validateContent(String content) throws PortalException {
3675                    if (Validator.isNull(content)) {
3676                            throw new ArticleContentException("Content is null");
3677                    }
3678    
3679                    try {
3680                            SAXReaderUtil.read(content);
3681                    }
3682                    catch (DocumentException de) {
3683                            if (_log.isDebugEnabled()) {
3684                                    _log.debug("Invalid content:\n" + content);
3685                            }
3686    
3687                            throw new ArticleContentException(
3688                                    "Unable to read content with an XML parser", de);
3689                    }
3690            }
3691    
3692            private static final long _JOURNAL_ARTICLE_CHECK_INTERVAL =
3693                    PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
3694    
3695            private static Log _log = LogFactoryUtil.getLog(
3696                    JournalArticleLocalServiceImpl.class);
3697    
3698            private Date _previousCheckDate;
3699    
3700    }