001    /**
002     * Copyright (c) 2000-2010 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.NoSuchImageException;
018    import com.liferay.portal.NoSuchUserException;
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.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.mail.MailMessage;
025    import com.liferay.portal.kernel.messaging.DestinationNames;
026    import com.liferay.portal.kernel.messaging.Message;
027    import com.liferay.portal.kernel.messaging.MessageBusUtil;
028    import com.liferay.portal.kernel.search.Indexer;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.servlet.ImageServletTokenUtil;
031    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
032    import com.liferay.portal.kernel.util.ContentTypes;
033    import com.liferay.portal.kernel.util.FileUtil;
034    import com.liferay.portal.kernel.util.GetterUtil;
035    import com.liferay.portal.kernel.util.HtmlUtil;
036    import com.liferay.portal.kernel.util.HttpUtil;
037    import com.liferay.portal.kernel.util.LocaleUtil;
038    import com.liferay.portal.kernel.util.LocalizationUtil;
039    import com.liferay.portal.kernel.util.MathUtil;
040    import com.liferay.portal.kernel.util.OrderByComparator;
041    import com.liferay.portal.kernel.util.PropsKeys;
042    import com.liferay.portal.kernel.util.StringPool;
043    import com.liferay.portal.kernel.util.StringUtil;
044    import com.liferay.portal.kernel.util.Time;
045    import com.liferay.portal.kernel.util.Validator;
046    import com.liferay.portal.kernel.workflow.WorkflowConstants;
047    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
048    import com.liferay.portal.kernel.xml.Document;
049    import com.liferay.portal.kernel.xml.DocumentException;
050    import com.liferay.portal.kernel.xml.Element;
051    import com.liferay.portal.kernel.xml.Node;
052    import com.liferay.portal.kernel.xml.SAXReaderUtil;
053    import com.liferay.portal.kernel.xml.XPath;
054    import com.liferay.portal.model.Company;
055    import com.liferay.portal.model.Group;
056    import com.liferay.portal.model.Image;
057    import com.liferay.portal.model.PortletPreferencesIds;
058    import com.liferay.portal.model.ResourceConstants;
059    import com.liferay.portal.model.User;
060    import com.liferay.portal.service.ServiceContext;
061    import com.liferay.portal.service.ServiceContextUtil;
062    import com.liferay.portal.servlet.filters.cache.CacheUtil;
063    import com.liferay.portal.theme.ThemeDisplay;
064    import com.liferay.portal.util.PortalUtil;
065    import com.liferay.portal.util.PortletKeys;
066    import com.liferay.portal.util.PrefsPropsUtil;
067    import com.liferay.portal.util.PropsUtil;
068    import com.liferay.portal.util.PropsValues;
069    import com.liferay.portlet.asset.NoSuchEntryException;
070    import com.liferay.portlet.asset.model.AssetEntry;
071    import com.liferay.portlet.expando.model.ExpandoBridge;
072    import com.liferay.portlet.journal.ArticleContentException;
073    import com.liferay.portlet.journal.ArticleDisplayDateException;
074    import com.liferay.portlet.journal.ArticleExpirationDateException;
075    import com.liferay.portlet.journal.ArticleIdException;
076    import com.liferay.portlet.journal.ArticleReviewDateException;
077    import com.liferay.portlet.journal.ArticleSmallImageNameException;
078    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
079    import com.liferay.portlet.journal.ArticleTitleException;
080    import com.liferay.portlet.journal.ArticleTypeException;
081    import com.liferay.portlet.journal.ArticleVersionException;
082    import com.liferay.portlet.journal.DuplicateArticleIdException;
083    import com.liferay.portlet.journal.NoSuchArticleException;
084    import com.liferay.portlet.journal.NoSuchArticleResourceException;
085    import com.liferay.portlet.journal.NoSuchStructureException;
086    import com.liferay.portlet.journal.NoSuchTemplateException;
087    import com.liferay.portlet.journal.StructureXsdException;
088    import com.liferay.portlet.journal.model.JournalArticle;
089    import com.liferay.portlet.journal.model.JournalArticleConstants;
090    import com.liferay.portlet.journal.model.JournalArticleDisplay;
091    import com.liferay.portlet.journal.model.JournalStructure;
092    import com.liferay.portlet.journal.model.JournalTemplate;
093    import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
094    import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
095    import com.liferay.portlet.journal.util.JournalUtil;
096    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
097    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
098    import com.liferay.portlet.journalcontent.util.JournalContentUtil;
099    
100    import java.io.File;
101    import java.io.IOException;
102    
103    import java.util.Calendar;
104    import java.util.Date;
105    import java.util.HashSet;
106    import java.util.List;
107    import java.util.Map;
108    import java.util.Set;
109    
110    import javax.mail.internet.InternetAddress;
111    
112    import javax.portlet.PortletPreferences;
113    
114    /**
115     * @author Brian Wing Shun Chan
116     * @author Raymond Augé
117     * @author Bruno Farache
118     */
119    public class JournalArticleLocalServiceImpl
120            extends JournalArticleLocalServiceBaseImpl {
121    
122            public JournalArticle addArticle(
123                            long userId, long groupId, String articleId, boolean autoArticleId,
124                            double version, String title, String description, String content,
125                            String type, String structureId, String templateId,
126                            int displayDateMonth, int displayDateDay, int displayDateYear,
127                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
128                            int expirationDateDay, int expirationDateYear,
129                            int expirationDateHour, int expirationDateMinute,
130                            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
131                            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
132                            boolean neverReview, boolean indexable, boolean smallImage,
133                            String smallImageURL, File smallFile, Map<String, byte[]> images,
134                            String articleURL, ServiceContext serviceContext)
135                    throws PortalException, SystemException {
136    
137                    // Article
138    
139                    User user = userPersistence.findByPrimaryKey(userId);
140                    articleId = articleId.trim().toUpperCase();
141    
142                    Date displayDate = PortalUtil.getDate(
143                            displayDateMonth, displayDateDay, displayDateYear,
144                            displayDateHour, displayDateMinute, user.getTimeZone(),
145                            new ArticleDisplayDateException());
146    
147                    Date expirationDate = null;
148    
149                    if (!neverExpire) {
150                            expirationDate = PortalUtil.getDate(
151                                    expirationDateMonth, expirationDateDay, expirationDateYear,
152                                    expirationDateHour, expirationDateMinute, user.getTimeZone(),
153                                    new ArticleExpirationDateException());
154                    }
155    
156                    Date reviewDate = null;
157    
158                    if (!neverReview) {
159                            reviewDate = PortalUtil.getDate(
160                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
161                                    reviewDateMinute, user.getTimeZone(),
162                                    new ArticleReviewDateException());
163                    }
164    
165                    byte[] smallBytes = null;
166    
167                    try {
168                            smallBytes = FileUtil.getBytes(smallFile);
169                    }
170                    catch (IOException ioe) {
171                    }
172    
173                    Date now = new Date();
174    
175                    validate(
176                            user.getCompanyId(), groupId, articleId, autoArticleId, version,
177                            title, content, type, structureId, templateId, smallImage,
178                            smallImageURL, smallFile, smallBytes);
179    
180                    if (autoArticleId) {
181                            articleId = String.valueOf(counterLocalService.increment());
182                    }
183    
184                    long id = counterLocalService.increment();
185    
186                    long resourcePrimKey =
187                            journalArticleResourceLocalService.getArticleResourcePrimKey(
188                                    groupId, articleId);
189    
190                    JournalArticle article = journalArticlePersistence.create(id);
191    
192                    content = format(
193                            groupId, articleId, version, false, content, structureId, images);
194    
195                    article.setUuid(serviceContext.getUuid());
196                    article.setResourcePrimKey(resourcePrimKey);
197                    article.setGroupId(groupId);
198                    article.setCompanyId(user.getCompanyId());
199                    article.setUserId(user.getUserId());
200                    article.setUserName(user.getFullName());
201                    article.setCreateDate(serviceContext.getCreateDate(now));
202                    article.setModifiedDate(serviceContext.getModifiedDate(now));
203                    article.setArticleId(articleId);
204                    article.setVersion(version);
205                    article.setTitle(title);
206                    article.setUrlTitle(getUniqueUrlTitle(id, groupId, articleId, title));
207                    article.setDescription(description);
208                    article.setContent(content);
209                    article.setType(type);
210                    article.setStructureId(structureId);
211                    article.setTemplateId(templateId);
212                    article.setDisplayDate(displayDate);
213    
214                    if ((expirationDate == null) || expirationDate.after(now)) {
215                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
216                    }
217                    else {
218                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
219                    }
220    
221                    article.setExpirationDate(expirationDate);
222                    article.setReviewDate(reviewDate);
223                    article.setIndexable(indexable);
224                    article.setSmallImage(smallImage);
225                    article.setSmallImageId(counterLocalService.increment());
226                    article.setSmallImageURL(smallImageURL);
227    
228                    journalArticlePersistence.update(article, false);
229    
230                    // Resources
231    
232                    if (serviceContext.getAddCommunityPermissions() ||
233                            serviceContext.getAddGuestPermissions()) {
234    
235                            addArticleResources(
236                                    article, serviceContext.getAddCommunityPermissions(),
237                                    serviceContext.getAddGuestPermissions());
238                    }
239                    else {
240                            addArticleResources(
241                                    article, serviceContext.getCommunityPermissions(),
242                                    serviceContext.getGuestPermissions());
243                    }
244    
245                    // Expando
246    
247                    ExpandoBridge expandoBridge = article.getExpandoBridge();
248    
249                    expandoBridge.setAttributes(serviceContext);
250    
251                    // Small image
252    
253                    saveImages(
254                            smallImage, article.getSmallImageId(), smallFile, smallBytes);
255    
256                    // Asset
257    
258                    updateAsset(
259                            userId, article, serviceContext.getAssetCategoryIds(),
260                            serviceContext.getAssetTagNames());
261    
262                    // Message boards
263    
264                    if (PropsValues.JOURNAL_ARTICLE_COMMENTS_ENABLED) {
265                            mbMessageLocalService.addDiscussionMessage(
266                                    userId, article.getUserName(), groupId,
267                                    JournalArticle.class.getName(), resourcePrimKey,
268                                    WorkflowConstants.ACTION_PUBLISH);
269                    }
270    
271                    // Email
272    
273                    PortletPreferences preferences =
274                            ServiceContextUtil.getPortletPreferences(serviceContext);
275    
276                    try {
277                            sendEmail(article, articleURL, preferences, "requested");
278                    }
279                    catch (IOException ioe) {
280                            throw new SystemException(ioe);
281                    }
282    
283                    // Workflow
284    
285                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
286                            user.getCompanyId(), groupId, userId,
287                            JournalArticle.class.getName(), article.getResourcePrimKey(),
288                            article, serviceContext);
289    
290                    return article;
291            }
292    
293            public void addArticleResources(
294                            JournalArticle article, boolean addCommunityPermissions,
295                            boolean addGuestPermissions)
296                    throws PortalException, SystemException {
297    
298                    resourceLocalService.addResources(
299                            article.getCompanyId(), article.getGroupId(),
300                            article.getUserId(), JournalArticle.class.getName(),
301                            article.getResourcePrimKey(), false, addCommunityPermissions,
302                            addGuestPermissions);
303            }
304    
305            public void addArticleResources(
306                            JournalArticle article, String[] communityPermissions,
307                            String[] guestPermissions)
308                    throws PortalException, SystemException {
309    
310                    resourceLocalService.addModelResources(
311                            article.getCompanyId(), article.getGroupId(),
312                            article.getUserId(), JournalArticle.class.getName(),
313                            article.getResourcePrimKey(), communityPermissions,
314                            guestPermissions);
315            }
316    
317            public void addArticleResources(
318                            long groupId, String articleId, boolean addCommunityPermissions,
319                            boolean addGuestPermissions)
320                    throws PortalException, SystemException {
321    
322                    JournalArticle article = getLatestArticle(groupId, articleId);
323    
324                    addArticleResources(
325                            article, addCommunityPermissions, addGuestPermissions);
326            }
327    
328            public void addArticleResources(
329                            long groupId, String articleId, String[] communityPermissions,
330                            String[] guestPermissions)
331                    throws PortalException, SystemException {
332    
333                    JournalArticle article = getLatestArticle(groupId, articleId);
334    
335                    addArticleResources(article, communityPermissions, guestPermissions);
336            }
337    
338            public JournalArticle checkArticleResourcePrimKey(
339                            long groupId, String articleId, double version)
340                    throws PortalException, SystemException {
341    
342                    JournalArticle article = journalArticlePersistence.findByG_A_V(
343                            groupId, articleId, version);
344    
345                    if (article.getResourcePrimKey() > 0) {
346                            return article;
347                    }
348    
349                    long resourcePrimKey =
350                            journalArticleResourceLocalService.getArticleResourcePrimKey(
351                                    groupId, articleId);
352    
353                    article.setResourcePrimKey(resourcePrimKey);
354    
355                    journalArticlePersistence.update(article, false);
356    
357                    return article;
358            }
359    
360            public void checkArticles() throws PortalException, SystemException {
361                    Date now = new Date();
362    
363                    List<JournalArticle> articles =
364                            journalArticleFinder.findByExpirationDate(
365                                    WorkflowConstants.STATUS_APPROVED, now,
366                                    new Date(now.getTime() - _journalArticleCheckInterval));
367    
368                    if (_log.isDebugEnabled()) {
369                            _log.debug("Expiring " + articles.size() + " articles");
370                    }
371    
372                    Set<Long> companyIds = new HashSet<Long>();
373    
374                    for (JournalArticle article : articles) {
375                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
376    
377                            journalArticlePersistence.update(article, false);
378    
379                            if (article.isIndexable()) {
380                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
381                                            JournalArticle.class);
382    
383                                    indexer.delete(article);
384                            }
385    
386                            JournalContentUtil.clearCache(
387                                    article.getGroupId(), article.getArticleId(),
388                                    article.getTemplateId());
389    
390                            companyIds.add(article.getCompanyId());
391                    }
392    
393                    for (long companyId : companyIds) {
394                            CacheUtil.clearCache(companyId);
395                    }
396    
397                    articles = journalArticleFinder.findByReviewDate(
398                            now, new Date(now.getTime() - _journalArticleCheckInterval));
399    
400                    if (_log.isDebugEnabled()) {
401                            _log.debug(
402                                    "Sending review notifications for " + articles.size() +
403                                            " articles");
404                    }
405    
406                    for (JournalArticle article : articles) {
407                            String articleURL = StringPool.BLANK;
408    
409                            long ownerId = article.getGroupId();
410                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
411                            long plid = PortletKeys.PREFS_PLID_SHARED;
412                            String portletId = PortletKeys.JOURNAL;
413    
414                            PortletPreferences preferences =
415                                    portletPreferencesLocalService.getPreferences(
416                                            article.getCompanyId(), ownerId, ownerType, plid,
417                                            portletId);
418    
419                            try {
420                                    sendEmail(article, articleURL, preferences, "review");
421                            }
422                            catch (IOException ioe) {
423                                    throw new SystemException(ioe);
424                            }
425                    }
426            }
427    
428            public void checkNewLine(long groupId, String articleId, double version)
429                    throws PortalException, SystemException {
430    
431                    JournalArticle article = journalArticlePersistence.findByG_A_V(
432                            groupId, articleId, version);
433    
434                    String content = GetterUtil.getString(article.getContent());
435    
436                    if (content.indexOf("\\n") != -1) {
437                            content = StringUtil.replace(
438                                    content,
439                                    new String[] {"\\n", "\\r"},
440                                    new String[] {"\n", "\r"});
441    
442                            article.setContent(content);
443    
444                            journalArticlePersistence.update(article, false);
445                    }
446            }
447    
448            public void checkStructure(long groupId, String articleId, double version)
449                    throws PortalException, SystemException {
450    
451                    JournalArticle article = journalArticlePersistence.findByG_A_V(
452                            groupId, articleId, version);
453    
454                    if (Validator.isNull(article.getStructureId())) {
455                            return;
456                    }
457    
458                    try {
459                            checkStructure(article);
460                    }
461                    catch (DocumentException de) {
462                            _log.error(de, de);
463                    }
464            }
465    
466            public JournalArticle copyArticle(
467                            long userId, long groupId, String oldArticleId, String newArticleId,
468                            boolean autoArticleId, double version)
469                    throws PortalException, SystemException {
470    
471                    // Article
472    
473                    User user = userPersistence.findByPrimaryKey(userId);
474                    oldArticleId = oldArticleId.trim().toUpperCase();
475                    newArticleId = newArticleId.trim().toUpperCase();
476                    Date now = new Date();
477    
478                    JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
479                            groupId, oldArticleId, version);
480    
481                    if (autoArticleId) {
482                            newArticleId = String.valueOf(counterLocalService.increment());
483                    }
484                    else {
485                            validate(newArticleId);
486    
487                            JournalArticle newArticle = journalArticlePersistence.fetchByG_A_V(
488                                    groupId, newArticleId, version);
489    
490                            if (newArticle != null) {
491                                    throw new DuplicateArticleIdException();
492                            }
493                    }
494    
495                    long id = counterLocalService.increment();
496    
497                    long resourcePrimKey =
498                            journalArticleResourceLocalService.getArticleResourcePrimKey(
499                                    groupId, newArticleId);
500    
501                    JournalArticle newArticle = journalArticlePersistence.create(id);
502    
503                    newArticle.setResourcePrimKey(resourcePrimKey);
504                    newArticle.setGroupId(groupId);
505                    newArticle.setCompanyId(user.getCompanyId());
506                    newArticle.setUserId(user.getUserId());
507                    newArticle.setUserName(user.getFullName());
508                    newArticle.setCreateDate(now);
509                    newArticle.setModifiedDate(now);
510                    newArticle.setArticleId(newArticleId);
511                    newArticle.setVersion(JournalArticleConstants.DEFAULT_VERSION);
512                    newArticle.setTitle(oldArticle.getTitle());
513                    newArticle.setDescription(oldArticle.getDescription());
514    
515                    try {
516                            copyArticleImages(oldArticle, newArticle);
517                    }
518                    catch (Exception e) {
519                            newArticle.setContent(oldArticle.getContent());
520                    }
521    
522                    newArticle.setType(oldArticle.getType());
523                    newArticle.setStructureId(oldArticle.getStructureId());
524                    newArticle.setTemplateId(oldArticle.getTemplateId());
525                    newArticle.setDisplayDate(oldArticle.getDisplayDate());
526                    newArticle.setStatus(oldArticle.getStatus());
527                    newArticle.setExpirationDate(oldArticle.getExpirationDate());
528                    newArticle.setReviewDate(oldArticle.getReviewDate());
529                    newArticle.setIndexable(oldArticle.isIndexable());
530                    newArticle.setSmallImage(oldArticle.isSmallImage());
531                    newArticle.setSmallImageId(counterLocalService.increment());
532                    newArticle.setSmallImageURL(oldArticle.getSmallImageURL());
533    
534                    journalArticlePersistence.update(newArticle, false);
535    
536                    // Resources
537    
538                    addArticleResources(newArticle, true, true);
539    
540                    // Small image
541    
542                    if (oldArticle.getSmallImage()) {
543                            Image image = imageLocalService.getImage(
544                                    oldArticle.getSmallImageId());
545    
546                            byte[] smallBytes = image.getTextObj();
547    
548                            imageLocalService.updateImage(
549                                    newArticle.getSmallImageId(), smallBytes);
550                    }
551    
552                    // Asset
553    
554                    String[] assetTagNames = assetTagLocalService.getTagNames(
555                            JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
556    
557                    updateAsset(userId, newArticle, null, assetTagNames);
558    
559                    return newArticle;
560            }
561    
562            public void deleteArticle(
563                            JournalArticle article, String articleURL,
564                            ServiceContext serviceContext)
565                    throws PortalException, SystemException {
566    
567                    if (article.isApproved() &&
568                            isLatestVersion(
569                                    article.getGroupId(), article.getArticleId(),
570                                    article.getVersion(), WorkflowConstants.STATUS_APPROVED)) {
571    
572                            updatePreviousApprovedArticle(article);
573                    }
574    
575                    // Email
576    
577                    PortletPreferences preferences =
578                            ServiceContextUtil.getPortletPreferences(serviceContext);
579    
580                    if ((preferences != null) && !article.isApproved() &&
581                            isLatestVersion(
582                                    article.getGroupId(), article.getArticleId(),
583                                    article.getVersion())) {
584    
585                            try {
586                                    sendEmail(article, articleURL, preferences, "denied");
587                            }
588                            catch (IOException ioe) {
589                                    throw new SystemException(ioe);
590                            }
591                    }
592    
593                    // Images
594    
595                    journalArticleImageLocalService.deleteImages(
596                            article.getGroupId(), article.getArticleId(), article.getVersion());
597    
598                    // Workflow
599    
600                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
601                            article.getCompanyId(), article.getGroupId(),
602                            JournalArticle.class.getName(), article.getResourcePrimKey());
603    
604                    int articlesCount = journalArticlePersistence.countByG_A(
605                            article.getGroupId(), article.getArticleId());
606    
607                    if (articlesCount == 1) {
608    
609                            // Ratings
610    
611                            ratingsStatsLocalService.deleteStats(
612                                    JournalArticle.class.getName(), article.getResourcePrimKey());
613    
614                            // Message boards
615    
616                            mbMessageLocalService.deleteDiscussionMessages(
617                                    JournalArticle.class.getName(), article.getResourcePrimKey());
618    
619                            // Asset
620    
621                            assetEntryLocalService.deleteEntry(
622                                    JournalArticle.class.getName(), article.getResourcePrimKey());
623    
624                            // Content searches
625    
626                            journalContentSearchLocalService.deleteArticleContentSearches(
627                                    article.getGroupId(), article.getArticleId());
628    
629                            // Small image
630    
631                            imageLocalService.deleteImage(article.getSmallImageId());
632    
633                            // Expando
634    
635                            expandoValueLocalService.deleteValues(
636                                    JournalArticle.class.getName(), article.getResourcePrimKey());
637    
638                            // Resources
639    
640                            resourceLocalService.deleteResource(
641                                    article.getCompanyId(), JournalArticle.class.getName(),
642                                    ResourceConstants.SCOPE_INDIVIDUAL,
643                                    article.getResourcePrimKey());
644    
645                            // Resource
646    
647                            try {
648                                    journalArticleResourceLocalService.deleteArticleResource(
649                                            article.getGroupId(), article.getArticleId());
650                            }
651                            catch (NoSuchArticleResourceException nsare) {
652                            }
653                    }
654    
655                    // Article
656    
657                    journalArticlePersistence.remove(article);
658            }
659    
660            public void deleteArticle(
661                            long groupId, String articleId, double version, String articleURL,
662                            ServiceContext serviceContext)
663                    throws PortalException, SystemException {
664    
665                    JournalArticle article = journalArticlePersistence.findByG_A_V(
666                            groupId, articleId, version);
667    
668                    deleteArticle(article, articleURL, serviceContext);
669            }
670    
671            public void deleteArticle(
672                            long groupId, String articleId, ServiceContext serviceContext)
673                    throws PortalException, SystemException {
674    
675                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
676                            groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
677                            new ArticleVersionComparator(true));
678    
679                    for (JournalArticle article : articles) {
680                            deleteArticle(article, null, serviceContext);
681                    }
682            }
683    
684            public void deleteArticles(long groupId)
685                    throws PortalException, SystemException {
686    
687                    for (JournalArticle article :
688                                    journalArticlePersistence.findByGroupId(groupId)) {
689    
690                            deleteArticle(article, null, null);
691                    }
692            }
693    
694            public JournalArticle expireArticle(
695                            long userId, long groupId, String articleId, double version,
696                            String articleURL, ServiceContext serviceContext)
697                    throws PortalException, SystemException {
698    
699                    return updateStatus(
700                            userId, groupId, articleId, version,
701                            WorkflowConstants.STATUS_EXPIRED, articleURL, serviceContext);
702            }
703    
704            public JournalArticle getArticle(long id)
705                    throws PortalException, SystemException {
706    
707                    return journalArticlePersistence.findByPrimaryKey(id);
708            }
709    
710            public JournalArticle getArticle(long groupId, String articleId)
711                    throws PortalException, SystemException {
712    
713                    // Get the latest article that is approved, if none are approved, get
714                    // the latest unapproved article
715    
716                    try {
717                            return getLatestArticle(
718                                    groupId, articleId, WorkflowConstants.STATUS_APPROVED);
719                    }
720                    catch (NoSuchArticleException nsae) {
721                            return getLatestArticle(
722                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
723                    }
724            }
725    
726            public JournalArticle getArticle(
727                            long groupId, String articleId, double version)
728                    throws PortalException, SystemException {
729    
730                    return journalArticlePersistence.findByG_A_V(
731                            groupId, articleId, version);
732            }
733    
734            public JournalArticle getArticleByUrlTitle(long groupId, String urlTitle)
735                    throws PortalException, SystemException {
736    
737                    // Get the latest article that is approved, if none are approved, get
738                    // the latest unapproved article
739    
740                    try {
741                            return getLatestArticleByUrlTitle(
742                                    groupId, urlTitle, WorkflowConstants.STATUS_APPROVED);
743                    }
744                    catch (NoSuchArticleException nsae) {
745                            return getLatestArticleByUrlTitle(
746                                    groupId, urlTitle, WorkflowConstants.STATUS_PENDING);
747                    }
748            }
749    
750            public String getArticleContent(
751                            JournalArticle article, String templateId, String viewMode,
752                            String languageId, ThemeDisplay themeDisplay)
753                    throws PortalException, SystemException {
754    
755                    JournalArticleDisplay articleDisplay = getArticleDisplay(
756                            article, templateId, viewMode, languageId, 1, null, themeDisplay);
757    
758                    if (articleDisplay == null) {
759                            return StringPool.BLANK;
760                    }
761                    else {
762                            return articleDisplay.getContent();
763                    }
764            }
765    
766            public String getArticleContent(
767                            long groupId, String articleId, double version, String viewMode,
768                            String templateId, String languageId, ThemeDisplay themeDisplay)
769                    throws PortalException, SystemException {
770    
771                    JournalArticleDisplay articleDisplay = getArticleDisplay(
772                            groupId, articleId, version, templateId, viewMode, languageId,
773                            themeDisplay);
774    
775                    if (articleDisplay == null) {
776                            return StringPool.BLANK;
777                    }
778                    else {
779                            return articleDisplay.getContent();
780                    }
781            }
782    
783            public String getArticleContent(
784                            long groupId, String articleId, double version, String viewMode,
785                            String languageId, ThemeDisplay themeDisplay)
786                    throws PortalException, SystemException {
787    
788                    return getArticleContent(
789                            groupId, articleId, version, viewMode, null, languageId,
790                            themeDisplay);
791            }
792    
793            public String getArticleContent(
794                            long groupId, String articleId, String viewMode, String templateId,
795                            String languageId, ThemeDisplay themeDisplay)
796                    throws PortalException, SystemException {
797    
798                    JournalArticleDisplay articleDisplay = getArticleDisplay(
799                            groupId, articleId, templateId, viewMode, languageId, themeDisplay);
800    
801                    return articleDisplay.getContent();
802            }
803    
804            public String getArticleContent(
805                            long groupId, String articleId, String viewMode, String languageId,
806                            ThemeDisplay themeDisplay)
807                    throws PortalException, SystemException {
808    
809                    return getArticleContent(
810                            groupId, articleId, viewMode, null, languageId, themeDisplay);
811            }
812    
813            public JournalArticleDisplay getArticleDisplay(
814                            JournalArticle article, String templateId, String viewMode,
815                            String languageId, int page, String xmlRequest,
816                            ThemeDisplay themeDisplay)
817                    throws PortalException, SystemException {
818    
819                    String content = null;
820    
821                    if (page < 1) {
822                            page = 1;
823                    }
824    
825                    int numberOfPages = 1;
826                    boolean paginate = false;
827                    boolean pageFlow = false;
828    
829                    boolean cacheable = true;
830    
831                    if (Validator.isNull(xmlRequest)) {
832                            xmlRequest = "<request />";
833                    }
834    
835                    Map<String, String> tokens = JournalUtil.getTokens(
836                            article.getGroupId(), themeDisplay, xmlRequest);
837    
838                    tokens.put(
839                            "article_resource_pk",
840                            String.valueOf(article.getResourcePrimKey()));
841    
842                    String defaultTemplateId = article.getTemplateId();
843    
844                    if (article.isTemplateDriven()) {
845                            if (Validator.isNull(templateId)) {
846                                    templateId = defaultTemplateId;
847                            }
848    
849                            tokens.put("structure_id", article.getStructureId());
850                            tokens.put("template_id", templateId);
851                    }
852    
853                    String xml = article.getContent();
854    
855                    try {
856                            Document doc = null;
857    
858                            Element root = null;
859    
860                            if (article.isTemplateDriven()) {
861                                    doc = SAXReaderUtil.read(xml);
862    
863                                    root = doc.getRootElement();
864    
865                                    Document request = SAXReaderUtil.read(xmlRequest);
866    
867                                    List<Element> pages = root.elements("page");
868    
869                                    if (pages.size() > 0) {
870                                            pageFlow = true;
871    
872                                            String targetPage = request.valueOf(
873                                                    "/request/parameters/parameter[name='targetPage']/" +
874                                                            "value");
875    
876                                            Element pageEl = null;
877    
878                                            if (Validator.isNotNull(targetPage)) {
879                                                    XPath xpathSelector = SAXReaderUtil.createXPath(
880                                                            "/root/page[@id = '" + targetPage + "']");
881    
882                                                    pageEl = (Element)xpathSelector.selectSingleNode(doc);
883                                            }
884    
885                                            if (pageEl != null) {
886                                                    doc = SAXReaderUtil.createDocument(pageEl);
887    
888                                                    root = doc.getRootElement();
889    
890                                                    numberOfPages = pages.size();
891                                            }
892                                            else {
893                                                    if (page > pages.size()) {
894                                                            page = 1;
895                                                    }
896    
897                                                    pageEl = pages.get(page - 1);
898    
899                                                    doc = SAXReaderUtil.createDocument(pageEl);
900    
901                                                    root = doc.getRootElement();
902    
903                                                    numberOfPages = pages.size();
904                                                    paginate = true;
905                                            }
906                                    }
907    
908                                    root.add(request.getRootElement().createCopy());
909    
910                                    JournalUtil.addAllReservedEls(root, tokens, article);
911    
912                                    xml = JournalUtil.formatXML(doc);
913                            }
914                    }
915                    catch (DocumentException de) {
916                            throw new SystemException(de);
917                    }
918                    catch (IOException ioe) {
919                            throw new SystemException(ioe);
920                    }
921    
922                    try {
923                            if (_log.isDebugEnabled()) {
924                                    _log.debug(
925                                            "Transforming " + article.getArticleId() + " " +
926                                                    article.getVersion() + " " + languageId);
927                            }
928    
929                            String script = null;
930                            String langType = null;
931    
932                            if (article.isTemplateDriven()) {
933    
934                                    // Try with specified template first (in the current group and
935                                    // the global group). If a template is not specified, use the
936                                    // default one. If the specified template does not exit, use the
937                                    // default one. If the default one does not exist, throw an
938                                    // exception.
939    
940                                    JournalTemplate template = null;
941    
942                                    try {
943                                            template = journalTemplatePersistence.findByG_T(
944                                                    article.getGroupId(), templateId);
945                                    }
946                                    catch (NoSuchTemplateException nste1) {
947                                            try {
948                                                    Group companyGroup = groupLocalService.getCompanyGroup(
949                                                            article.getCompanyId());
950    
951                                                    template = journalTemplatePersistence.findByG_T(
952                                                            companyGroup.getGroupId(), templateId);
953                                            }
954                                            catch (NoSuchTemplateException nste2) {
955                                                    if (!defaultTemplateId.equals(templateId)) {
956                                                            template = journalTemplatePersistence.findByG_T(
957                                                                    article.getGroupId(), defaultTemplateId);
958                                                    }
959                                                    else {
960                                                            throw nste1;
961                                                    }
962                                            }
963                                    }
964    
965                                    script = template.getXsl();
966                                    langType = template.getLangType();
967                                    cacheable = template.isCacheable();
968                            }
969    
970                            content = JournalUtil.transform(
971                                    themeDisplay, tokens, viewMode, languageId, xml, script,
972                                    langType);
973    
974                            if (!pageFlow) {
975                                    String[] pieces = StringUtil.split(content, _TOKEN_PAGE_BREAK);
976    
977                                    if (pieces.length > 1) {
978                                            if (page > pieces.length) {
979                                                    page = 1;
980                                            }
981    
982                                            content = pieces[page - 1];
983                                            numberOfPages = pieces.length;
984                                            paginate = true;
985                                    }
986                            }
987                    }
988                    catch (Exception e) {
989                            throw new SystemException(e);
990                    }
991    
992                    return new JournalArticleDisplayImpl(
993                            article.getCompanyId(), article.getId(),
994                            article.getResourcePrimKey(), article.getGroupId(),
995                            article.getUserId(), article.getArticleId(), article.getVersion(),
996                            article.getTitle(), article.getUrlTitle(), article.getDescription(),
997                            article.getAvailableLocales(), content, article.getType(),
998                            article.getStructureId(), templateId, article.isSmallImage(),
999                            article.getSmallImageId(), article.getSmallImageURL(),
1000                            numberOfPages, page, paginate, cacheable);
1001            }
1002    
1003            public JournalArticleDisplay getArticleDisplay(
1004                            long groupId, String articleId, double version, String templateId,
1005                            String viewMode, String languageId, int page, String xmlRequest,
1006                            ThemeDisplay themeDisplay)
1007                    throws PortalException, SystemException {
1008    
1009                    Date now = new Date();
1010    
1011                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1012                            groupId, articleId, version);
1013    
1014                    if (article.isExpired()) {
1015                            Date expirationDate = article.getExpirationDate();
1016    
1017                            if ((expirationDate != null) && expirationDate.before(now)) {
1018                                    return null;
1019                            }
1020                    }
1021    
1022                    if (article.getDisplayDate().after(now)) {
1023                            return null;
1024                    }
1025    
1026                    return getArticleDisplay(
1027                            article, templateId, viewMode, languageId, page, xmlRequest,
1028                            themeDisplay);
1029            }
1030    
1031            public JournalArticleDisplay getArticleDisplay(
1032                            long groupId, String articleId, double version, String templateId,
1033                            String viewMode, String languageId, ThemeDisplay themeDisplay)
1034                    throws PortalException, SystemException {
1035    
1036                    return getArticleDisplay(
1037                            groupId, articleId, version, templateId, viewMode, languageId, 1,
1038                            null, themeDisplay);
1039            }
1040    
1041            public JournalArticleDisplay getArticleDisplay(
1042                            long groupId, String articleId, String viewMode, String languageId,
1043                            int page, String xmlRequest, ThemeDisplay themeDisplay)
1044                    throws PortalException, SystemException {
1045    
1046                    return getArticleDisplay(
1047                            groupId, articleId, null, viewMode, languageId, page, xmlRequest,
1048                            themeDisplay);
1049            }
1050    
1051            public JournalArticleDisplay getArticleDisplay(
1052                            long groupId, String articleId, String templateId, String viewMode,
1053                            String languageId, int page, String xmlRequest,
1054                            ThemeDisplay themeDisplay)
1055                    throws PortalException, SystemException {
1056    
1057                    JournalArticle article = getDisplayArticle(groupId, articleId);
1058    
1059                    return getArticleDisplay(
1060                            groupId, articleId, article.getVersion(), templateId, viewMode,
1061                            languageId, page, xmlRequest, themeDisplay);
1062            }
1063    
1064            public JournalArticleDisplay getArticleDisplay(
1065                            long groupId, String articleId, String templateId, String viewMode,
1066                            String languageId, ThemeDisplay themeDisplay)
1067                    throws PortalException, SystemException {
1068    
1069                    JournalArticle article = getDisplayArticle(groupId, articleId);
1070    
1071                    return getArticleDisplay(
1072                            groupId, articleId, article.getVersion(), templateId, viewMode,
1073                            languageId, themeDisplay);
1074            }
1075    
1076            public JournalArticleDisplay getArticleDisplay(
1077                            long groupId, String articleId, String viewMode, String languageId,
1078                            ThemeDisplay themeDisplay)
1079                    throws PortalException, SystemException {
1080    
1081                    return getArticleDisplay(
1082                            groupId, articleId, null, viewMode, languageId, themeDisplay);
1083            }
1084    
1085            public List<JournalArticle> getArticles() throws SystemException {
1086                    return journalArticlePersistence.findAll();
1087            }
1088    
1089            public List<JournalArticle> getArticles(long groupId)
1090                    throws SystemException {
1091    
1092                    return journalArticlePersistence.findByGroupId(groupId);
1093            }
1094    
1095            public List<JournalArticle> getArticles(long groupId, int start, int end)
1096                    throws SystemException {
1097    
1098                    return journalArticlePersistence.findByGroupId(groupId, start, end);
1099            }
1100    
1101            public List<JournalArticle> getArticles(
1102                            long groupId, int start, int end, OrderByComparator obc)
1103                    throws SystemException {
1104    
1105                    return journalArticlePersistence.findByGroupId(
1106                            groupId, start, end, obc);
1107            }
1108    
1109            public List<JournalArticle> getArticles(long groupId, String articleId)
1110                    throws SystemException {
1111    
1112                    return journalArticlePersistence.findByG_A(groupId, articleId);
1113            }
1114    
1115            public List<JournalArticle> getArticlesBySmallImageId(long smallImageId)
1116                    throws SystemException {
1117    
1118                    return journalArticlePersistence.findBySmallImageId(smallImageId);
1119            }
1120    
1121            public int getArticlesCount(long groupId) throws SystemException {
1122                    return journalArticlePersistence.countByGroupId(groupId);
1123            }
1124    
1125            public List<JournalArticle> getCompanyArticles(
1126                            long companyId, int status, int start, int end)
1127                    throws SystemException {
1128    
1129                    if (status == WorkflowConstants.STATUS_ANY) {
1130                            return journalArticlePersistence.findByCompanyId(
1131                                    companyId, start, end, new ArticleIDComparator(true));
1132                    }
1133                    else {
1134                            return journalArticlePersistence.findByC_ST(
1135                                    companyId, status, start, end, new ArticleIDComparator(true));
1136                    }
1137            }
1138    
1139            public int getCompanyArticlesCount(long companyId, int status)
1140                    throws SystemException {
1141    
1142                    if (status == WorkflowConstants.STATUS_ANY) {
1143                            return journalArticlePersistence.countByCompanyId(companyId);
1144                    }
1145                    else {
1146                            return journalArticlePersistence.countByC_ST(companyId, status);
1147                    }
1148            }
1149    
1150            public JournalArticle getDisplayArticle(long groupId, String articleId)
1151                    throws PortalException, SystemException {
1152    
1153                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
1154                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1155    
1156                    if (articles.size() == 0) {
1157                            throw new NoSuchArticleException(
1158                                    "No approved JournalArticle with the key {groupId=" + groupId +
1159                                            ", " + "articleId=" + articleId + "}");
1160    
1161                    }
1162    
1163                    Date now = new Date();
1164    
1165                    for (int i = 0; i < articles.size(); i++) {
1166                            JournalArticle article = articles.get(i);
1167    
1168                            Date expirationDate = article.getExpirationDate();
1169    
1170                            if (article.getDisplayDate().before(now) &&
1171                                    ((expirationDate == null) || expirationDate.after(now))) {
1172    
1173                                    return article;
1174                            }
1175                    }
1176    
1177                    return articles.get(0);
1178            }
1179    
1180            public JournalArticle getLatestArticle(long resourcePrimKey)
1181                    throws PortalException, SystemException {
1182    
1183                    return getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
1184            }
1185    
1186            public JournalArticle getLatestArticle(long resourcePrimKey, int status)
1187                    throws PortalException, SystemException {
1188    
1189                    return getLatestArticle(resourcePrimKey, status, true);
1190            }
1191    
1192            public JournalArticle getLatestArticle(
1193                            long resourcePrimKey, int status, boolean preferApproved)
1194                    throws PortalException, SystemException {
1195    
1196                    List<JournalArticle> articles = null;
1197    
1198                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1199    
1200                    if (status == WorkflowConstants.STATUS_ANY) {
1201                            if (preferApproved) {
1202                                    articles = journalArticlePersistence.findByR_ST(
1203                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED, 0, 1,
1204                                            orderByComparator);
1205                            }
1206    
1207                            if ((articles == null) || (articles.size() == 0)) {
1208                                    articles = journalArticlePersistence.findByResourcePrimKey(
1209                                            resourcePrimKey, 0, 1, orderByComparator);
1210                            }
1211                    }
1212                    else {
1213                            articles = journalArticlePersistence.findByR_ST(
1214                                    resourcePrimKey, status, 0, 1, orderByComparator);
1215                    }
1216    
1217                    if (articles.size() == 0) {
1218                            throw new NoSuchArticleException(
1219                                    "No JournalArticle with the key {resourcePrimKey=" +
1220                                            resourcePrimKey + "}");
1221                    }
1222    
1223                    return articles.get(0);
1224            }
1225    
1226            public JournalArticle getLatestArticle(long groupId, String articleId)
1227                    throws PortalException, SystemException {
1228    
1229                    return getLatestArticle(
1230                            groupId, articleId, WorkflowConstants.STATUS_ANY);
1231            }
1232    
1233            public JournalArticle getLatestArticle(
1234                            long groupId, String articleId, int status)
1235                    throws PortalException, SystemException {
1236    
1237                    List<JournalArticle> articles = null;
1238    
1239                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1240    
1241                    if (status == WorkflowConstants.STATUS_ANY) {
1242                            articles = journalArticlePersistence.findByG_A(
1243                                    groupId, articleId, 0, 1, orderByComparator);
1244                    }
1245                    else {
1246                            articles = journalArticlePersistence.findByG_A_ST(
1247                                    groupId, articleId, status, 0, 1, orderByComparator);
1248                    }
1249    
1250                    if (articles.size() == 0) {
1251                            throw new NoSuchArticleException(
1252                                    "No JournalArticle with the key {groupId=" + groupId +
1253                                            ", articleId=" + articleId + ", status=" + status + "}");
1254                    }
1255    
1256                    return articles.get(0);
1257            }
1258    
1259            public JournalArticle getLatestArticleByUrlTitle(
1260                            long groupId, String urlTitle, int status)
1261                    throws PortalException, SystemException {
1262    
1263                    List<JournalArticle> articles = null;
1264    
1265                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1266    
1267                    if (status == WorkflowConstants.STATUS_ANY) {
1268                            articles = journalArticlePersistence.findByG_UT(
1269                                    groupId, urlTitle, 0, 1, orderByComparator);
1270                    }
1271                    else {
1272                            articles = journalArticlePersistence.findByG_UT_ST(
1273                                    groupId, urlTitle, status, 0, 1, orderByComparator);
1274                    }
1275    
1276                    if (articles.size() == 0) {
1277                            throw new NoSuchArticleException(
1278                                    "No JournalArticle with the key {groupId=" + groupId +
1279                                            ", urlTitle=" + urlTitle + ", status=" + status + "}");
1280                    }
1281    
1282                    return articles.get(0);
1283            }
1284    
1285            public double getLatestVersion(long groupId, String articleId)
1286                    throws PortalException, SystemException {
1287    
1288                    JournalArticle article = getLatestArticle(groupId, articleId);
1289    
1290                    return article.getVersion();
1291            }
1292    
1293            public double getLatestVersion(
1294                            long groupId, String articleId, int status)
1295                    throws PortalException, SystemException {
1296    
1297                    JournalArticle article = getLatestArticle(groupId, articleId, status);
1298    
1299                    return article.getVersion();
1300            }
1301    
1302            public List<JournalArticle> getStructureArticles(
1303                            long groupId, String structureId)
1304                    throws SystemException {
1305    
1306                    return journalArticlePersistence.findByG_S(groupId, structureId);
1307            }
1308    
1309            public List<JournalArticle> getStructureArticles(
1310                            long groupId, String structureId, int start, int end,
1311                            OrderByComparator obc)
1312                    throws SystemException {
1313    
1314                    return journalArticlePersistence.findByG_S(
1315                            groupId, structureId, start, end, obc);
1316            }
1317    
1318            public int getStructureArticlesCount(long groupId, String structureId)
1319                    throws SystemException {
1320    
1321                    return journalArticlePersistence.countByG_S(groupId, structureId);
1322            }
1323    
1324            public List<JournalArticle> getTemplateArticles(
1325                            long groupId, String templateId)
1326                    throws SystemException {
1327    
1328                    return journalArticlePersistence.findByG_T(groupId, templateId);
1329            }
1330    
1331            public List<JournalArticle> getTemplateArticles(
1332                            long groupId, String templateId, int start, int end,
1333                            OrderByComparator obc)
1334                    throws SystemException {
1335    
1336                    return journalArticlePersistence.findByG_T(
1337                            groupId, templateId, start, end, obc);
1338            }
1339    
1340            public int getTemplateArticlesCount(long groupId, String templateId)
1341                    throws SystemException {
1342    
1343                    return journalArticlePersistence.countByG_T(groupId, templateId);
1344            }
1345    
1346            public boolean hasArticle(long groupId, String articleId)
1347                    throws SystemException {
1348    
1349                    try {
1350                            getArticle(groupId, articleId);
1351    
1352                            return true;
1353                    }
1354                    catch (PortalException pe) {
1355                            return false;
1356                    }
1357            }
1358    
1359            public boolean isLatestVersion(
1360                            long groupId, String articleId, double version)
1361                    throws PortalException, SystemException {
1362    
1363                    if (getLatestVersion(groupId, articleId) == version) {
1364                            return true;
1365                    }
1366                    else {
1367                            return false;
1368                    }
1369            }
1370    
1371            public boolean isLatestVersion(
1372                            long groupId, String articleId, double version, int status)
1373                    throws PortalException, SystemException {
1374    
1375                    if (getLatestVersion(groupId, articleId, status) == version) {
1376                            return true;
1377                    }
1378                    else {
1379                            return false;
1380                    }
1381            }
1382    
1383            public JournalArticle removeArticleLocale(
1384                            long groupId, String articleId, double version, String languageId)
1385                    throws PortalException, SystemException {
1386    
1387                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1388                            groupId, articleId, version);
1389    
1390                    String content = article.getContent();
1391    
1392                    if (article.isTemplateDriven()) {
1393                            content = JournalUtil.removeArticleLocale(content, languageId);
1394                    }
1395                    else {
1396                            content = LocalizationUtil.removeLocalization(
1397                                    content, "static-content", languageId, true);
1398                    }
1399    
1400                    article.setContent(content);
1401    
1402                    journalArticlePersistence.update(article, false);
1403    
1404                    return article;
1405            }
1406    
1407            public List<JournalArticle> search(
1408                            long companyId, long groupId, String keywords, Double version,
1409                            String type, String structureId, String templateId,
1410                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1411                            int start, int end, OrderByComparator obc)
1412                    throws SystemException {
1413    
1414                    return journalArticleFinder.findByKeywords(
1415                            companyId, groupId, keywords, version, type, structureId,
1416                            templateId, displayDateGT, displayDateLT, status, reviewDate, start,
1417                            end, obc);
1418            }
1419    
1420            public List<JournalArticle> search(
1421                            long companyId, long groupId, String articleId, Double version,
1422                            String title, String description, String content, String type,
1423                            String structureId, String templateId, Date displayDateGT,
1424                            Date displayDateLT, int status, Date reviewDate,
1425                            boolean andOperator, int start, int end, OrderByComparator obc)
1426                    throws SystemException {
1427    
1428                    return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_S_R(
1429                            companyId, groupId, articleId, version, title, description, content,
1430                            type, structureId, templateId, displayDateGT, displayDateLT,
1431                            status, reviewDate, andOperator, start, end, obc);
1432            }
1433    
1434            public List<JournalArticle> search(
1435                            long companyId, long groupId, String articleId, Double version,
1436                            String title, String description, String content, String type,
1437                            String[] structureIds, String[] templateIds, Date displayDateGT,
1438                            Date displayDateLT, int status, Date reviewDate,
1439                            boolean andOperator, int start, int end, OrderByComparator obc)
1440                    throws SystemException {
1441    
1442                    return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_S_R(
1443                            companyId, groupId, articleId, version, title, description, content,
1444                            type, structureIds, templateIds, displayDateGT, displayDateLT,
1445                            status, reviewDate, andOperator, start, end, obc);
1446            }
1447    
1448            public int searchCount(
1449                            long companyId, long groupId, String keywords, Double version,
1450                            String type, String structureId, String templateId,
1451                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate)
1452                    throws SystemException {
1453    
1454                    return journalArticleFinder.countByKeywords(
1455                            companyId, groupId, keywords, version, type, structureId,
1456                            templateId, displayDateGT, displayDateLT, status, reviewDate);
1457            }
1458    
1459            public int searchCount(
1460                            long companyId, long groupId, String articleId, Double version,
1461                            String title, String description, String content, String type,
1462                            String structureId, String templateId, Date displayDateGT,
1463                            Date displayDateLT, int status, Date reviewDate,
1464                            boolean andOperator)
1465                    throws SystemException {
1466    
1467                    return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_S_R(
1468                            companyId, groupId, articleId, version, title, description, content,
1469                            type, structureId, templateId, displayDateGT, displayDateLT,
1470                            status, reviewDate, andOperator);
1471            }
1472    
1473            public int searchCount(
1474                            long companyId, long groupId, String articleId, Double version,
1475                            String title, String description, String content, String type,
1476                            String[] structureIds, String[] templateIds, Date displayDateGT,
1477                            Date displayDateLT, int status, Date reviewDate,
1478                            boolean andOperator)
1479                    throws SystemException {
1480    
1481                    return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_S_R(
1482                            companyId, groupId, articleId, version, title, description, content,
1483                            type, structureIds, templateIds, displayDateGT, displayDateLT,
1484                            status, reviewDate, andOperator);
1485            }
1486    
1487            public JournalArticle updateArticle(
1488                            long userId, long groupId, String articleId, double version,
1489                            String content)
1490                    throws PortalException, SystemException {
1491    
1492                    User user = userPersistence.findByPrimaryKey(userId);
1493    
1494                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1495                            groupId, articleId, version);
1496    
1497                    Date displayDate = article.getDisplayDate();
1498    
1499                    int displayDateMonth = 0;
1500                    int displayDateDay = 0;
1501                    int displayDateYear = 0;
1502                    int displayDateHour = 0;
1503                    int displayDateMinute = 0;
1504    
1505                    if (displayDate != null) {
1506                            Calendar displayCal = CalendarFactoryUtil.getCalendar(
1507                                    user.getTimeZone());
1508    
1509                            displayCal.setTime(displayDate);
1510    
1511                            displayDateMonth = displayCal.get(Calendar.MONTH);
1512                            displayDateDay = displayCal.get(Calendar.DATE);
1513                            displayDateYear = displayCal.get(Calendar.YEAR);
1514                            displayDateHour = displayCal.get(Calendar.HOUR);
1515                            displayDateMinute = displayCal.get(Calendar.MINUTE);
1516    
1517                            if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
1518                                    displayDateHour += 12;
1519                            }
1520                    }
1521    
1522                    Date expirationDate = article.getExpirationDate();
1523    
1524                    int expirationDateMonth = 0;
1525                    int expirationDateDay = 0;
1526                    int expirationDateYear = 0;
1527                    int expirationDateHour = 0;
1528                    int expirationDateMinute = 0;
1529                    boolean neverExpire = true;
1530    
1531                    if (expirationDate != null) {
1532                            Calendar expirationCal = CalendarFactoryUtil.getCalendar(
1533                                    user.getTimeZone());
1534    
1535                            expirationCal.setTime(expirationDate);
1536    
1537                            expirationDateMonth = expirationCal.get(Calendar.MONTH);
1538                            expirationDateDay = expirationCal.get(Calendar.DATE);
1539                            expirationDateYear = expirationCal.get(Calendar.YEAR);
1540                            expirationDateHour = expirationCal.get(Calendar.HOUR);
1541                            expirationDateMinute = expirationCal.get(Calendar.MINUTE);
1542                            neverExpire = false;
1543    
1544                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
1545                                    expirationDateHour += 12;
1546                            }
1547                    }
1548    
1549                    Date reviewDate = article.getReviewDate();
1550    
1551                    int reviewDateMonth = 0;
1552                    int reviewDateDay = 0;
1553                    int reviewDateYear = 0;
1554                    int reviewDateHour = 0;
1555                    int reviewDateMinute = 0;
1556                    boolean neverReview = true;
1557    
1558                    if (reviewDate != null) {
1559                            Calendar reviewCal = CalendarFactoryUtil.getCalendar(
1560                                    user.getTimeZone());
1561    
1562                            reviewCal.setTime(reviewDate);
1563    
1564                            reviewDateMonth = reviewCal.get(Calendar.MONTH);
1565                            reviewDateDay = reviewCal.get(Calendar.DATE);
1566                            reviewDateYear = reviewCal.get(Calendar.YEAR);
1567                            reviewDateHour = reviewCal.get(Calendar.HOUR);
1568                            reviewDateMinute = reviewCal.get(Calendar.MINUTE);
1569                            neverReview = false;
1570    
1571                            if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
1572                                    reviewDateHour += 12;
1573                            }
1574                    }
1575    
1576                    PortletPreferencesIds portletPreferencesIds = new PortletPreferencesIds(
1577                            article.getCompanyId(), PortletKeys.PREFS_OWNER_ID_DEFAULT,
1578                            PortletKeys.PREFS_OWNER_TYPE_LAYOUT, PortletKeys.PREFS_PLID_SHARED,
1579                            PortletKeys.JOURNAL);
1580    
1581                    ServiceContext serviceContext = new ServiceContext();
1582    
1583                    serviceContext.setPortletPreferencesIds(portletPreferencesIds);
1584    
1585                    return updateArticle(
1586                            userId, groupId, articleId, version, article.getTitle(),
1587                            article.getDescription(), content, article.getType(),
1588                            article.getStructureId(), article.getTemplateId(), displayDateMonth,
1589                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
1590                            expirationDateMonth, expirationDateDay, expirationDateYear,
1591                            expirationDateHour, expirationDateMinute, neverExpire,
1592                            reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1593                            reviewDateMinute, neverReview, article.getIndexable(),
1594                            article.isSmallImage(), article.getSmallImageURL(), null, null,
1595                            null, serviceContext);
1596            }
1597    
1598            public JournalArticle updateArticle(
1599                            long userId, long groupId, String articleId, double version,
1600                            String title, String description, String content, String type,
1601                            String structureId, String templateId, int displayDateMonth,
1602                            int displayDateDay, int displayDateYear, int displayDateHour,
1603                            int displayDateMinute, int expirationDateMonth,
1604                            int expirationDateDay, int expirationDateYear,
1605                            int expirationDateHour, int expirationDateMinute,
1606                            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
1607                            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
1608                            boolean neverReview, boolean indexable, boolean smallImage,
1609                            String smallImageURL, File smallFile, Map<String, byte[]> images,
1610                            String articleURL, ServiceContext serviceContext)
1611                    throws PortalException, SystemException {
1612    
1613                    // Article
1614    
1615                    User user = userPersistence.findByPrimaryKey(userId);
1616                    articleId = articleId.trim().toUpperCase();
1617    
1618                    Date displayDate = PortalUtil.getDate(
1619                            displayDateMonth, displayDateDay, displayDateYear,
1620                            displayDateHour, displayDateMinute, user.getTimeZone(),
1621                            new ArticleDisplayDateException());
1622    
1623                    Date expirationDate = null;
1624    
1625                    if (!neverExpire) {
1626                            expirationDate = PortalUtil.getDate(
1627                                    expirationDateMonth, expirationDateDay, expirationDateYear,
1628                                    expirationDateHour, expirationDateMinute, user.getTimeZone(),
1629                                    new ArticleExpirationDateException());
1630                    }
1631    
1632                    Date reviewDate = null;
1633    
1634                    if (!neverReview) {
1635                            reviewDate = PortalUtil.getDate(
1636                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1637                                    reviewDateMinute, user.getTimeZone(),
1638                                    new ArticleReviewDateException());
1639                    }
1640    
1641                    byte[] smallBytes = null;
1642    
1643                    try {
1644                            smallBytes = FileUtil.getBytes(smallFile);
1645                    }
1646                    catch (IOException ioe) {
1647                    }
1648    
1649                    Date now = new Date();
1650    
1651                    validate(
1652                            user.getCompanyId(), groupId, title, content, type, structureId,
1653                            templateId, smallImage, smallImageURL, smallFile, smallBytes);
1654    
1655                    JournalArticle oldArticle = null;
1656                    double oldVersion = 0;
1657    
1658                    boolean incrementVersion = false;
1659    
1660                    boolean imported = GetterUtil.getBoolean(
1661                            serviceContext.getAttribute("imported"));
1662    
1663                    if (imported) {
1664                            oldArticle = getArticle(groupId, articleId, version);
1665                            oldVersion = version;
1666                    }
1667                    else {
1668                            oldArticle = getLatestArticle(
1669                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
1670    
1671                            oldVersion = oldArticle.getVersion();
1672    
1673                            if ((version > 0) && (version != oldVersion)) {
1674                                    throw new ArticleVersionException();
1675                            }
1676    
1677                            if (oldArticle.isApproved() || oldArticle.isExpired()) {
1678                                    incrementVersion = true;
1679                            }
1680                    }
1681    
1682                    JournalArticle article = null;
1683    
1684                    if (incrementVersion) {
1685                            double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
1686    
1687                            long id = counterLocalService.increment();
1688    
1689                            article = journalArticlePersistence.create(id);
1690    
1691                            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1692                            article.setGroupId(oldArticle.getGroupId());
1693                            article.setCompanyId(user.getCompanyId());
1694                            article.setUserId(user.getUserId());
1695                            article.setUserName(user.getFullName());
1696                            article.setCreateDate(serviceContext.getModifiedDate(now));
1697                            article.setArticleId(articleId);
1698                            article.setVersion(newVersion);
1699                            article.setSmallImageId(oldArticle.getSmallImageId());
1700                    }
1701                    else {
1702                            article = oldArticle;
1703                    }
1704    
1705                    content = format(
1706                            groupId, articleId, article.getVersion(), incrementVersion,
1707                            content, structureId, images);
1708    
1709                    article.setModifiedDate(serviceContext.getModifiedDate(now));
1710                    article.setTitle(title);
1711                    article.setUrlTitle(
1712                            getUniqueUrlTitle(article.getId(), groupId, articleId, title));
1713                    article.setDescription(description);
1714                    article.setContent(content);
1715                    article.setType(type);
1716                    article.setStructureId(structureId);
1717                    article.setTemplateId(templateId);
1718                    article.setDisplayDate(displayDate);
1719    
1720                    if (oldArticle.isPending()) {
1721                            article.setStatus(oldArticle.getStatus());
1722                    }
1723                    else if ((expirationDate == null) || expirationDate.after(now)) {
1724                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
1725                    }
1726                    else {
1727                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
1728                    }
1729    
1730                    article.setExpirationDate(expirationDate);
1731                    article.setReviewDate(reviewDate);
1732                    article.setIndexable(indexable);
1733                    article.setSmallImage(smallImage);
1734    
1735                    if (article.getSmallImageId() == 0) {
1736                            article.setSmallImageId(counterLocalService.increment());
1737                    }
1738    
1739                    article.setSmallImageURL(smallImageURL);
1740    
1741                    journalArticlePersistence.update(article, false);
1742    
1743                    // Asset
1744    
1745                    long[] assetCategoryIds = serviceContext.getAssetCategoryIds();
1746                    String[] assetTagNames = serviceContext.getAssetTagNames();
1747    
1748                    updateAsset(userId, article, assetCategoryIds, assetTagNames);
1749    
1750                    // Expando
1751    
1752                    ExpandoBridge expandoBridge = article.getExpandoBridge();
1753    
1754                    expandoBridge.setAttributes(serviceContext);
1755    
1756                    // Small image
1757    
1758                    saveImages(
1759                            smallImage, article.getSmallImageId(), smallFile, smallBytes);
1760    
1761                    // Email
1762    
1763                    PortletPreferences preferences =
1764                            ServiceContextUtil.getPortletPreferences(serviceContext);
1765    
1766                    // Workflow
1767    
1768                    if (serviceContext.getWorkflowAction() ==
1769                                    WorkflowConstants.ACTION_PUBLISH) {
1770    
1771                            try {
1772                                    sendEmail(article, articleURL, preferences, "requested");
1773                            }
1774                            catch (IOException ioe) {
1775                                    throw new SystemException(ioe);
1776                            }
1777    
1778                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
1779                                    user.getCompanyId(), groupId, userId,
1780                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
1781                                    article, serviceContext);
1782                    }
1783    
1784                    return article;
1785            }
1786    
1787            public void updateAsset(
1788                            long userId, JournalArticle article, long[] assetCategoryIds,
1789                            String[] assetTagNames)
1790                    throws PortalException, SystemException {
1791    
1792                    // Get the earliest display date and latest expiration date among
1793                    // all article versions
1794    
1795                    Date[] dateInterval = getDateInterval(
1796                            article.getGroupId(), article.getArticleId(),
1797                            article.getDisplayDate(), article.getExpirationDate());
1798    
1799                    Date displayDate = dateInterval[0];
1800                    Date expirationDate = dateInterval[1];
1801    
1802                    boolean visible = article.isApproved();
1803    
1804                    boolean addDraftAssetEntry = false;
1805    
1806                    if (!article.isApproved() &&
1807                            (article.getVersion() != JournalArticleConstants.DEFAULT_VERSION)) {
1808    
1809                            int approvedArticlesCount =
1810                                    journalArticlePersistence.countByG_A_ST(
1811                                            article.getGroupId(), article.getArticleId(),
1812                                            WorkflowConstants.STATUS_APPROVED);
1813    
1814                            if (approvedArticlesCount > 0) {
1815                                    addDraftAssetEntry = true;
1816                            }
1817                    }
1818    
1819                    if (addDraftAssetEntry) {
1820                            assetEntryLocalService.updateEntry(
1821                                    userId, article.getGroupId(), JournalArticle.class.getName(),
1822                                    article.getPrimaryKey(), article.getUuid(), assetCategoryIds,
1823                                    assetTagNames, false, null, null, displayDate, expirationDate,
1824                                    ContentTypes.TEXT_HTML, article.getTitle(),
1825                                    article.getDescription(), null, null, 0, 0, null, false);
1826                    }
1827                    else {
1828                            assetEntryLocalService.updateEntry(
1829                                    userId, article.getGroupId(), JournalArticle.class.getName(),
1830                                    article.getResourcePrimKey(), article.getUuid(),
1831                                    assetCategoryIds, assetTagNames, visible, null, null,
1832                                    displayDate, expirationDate, ContentTypes.TEXT_HTML,
1833                                    article.getTitle(), article.getDescription(), null, null, 0, 0,
1834                                    null, false);
1835                    }
1836            }
1837    
1838            public JournalArticle updateContent(
1839                            long groupId, String articleId, double version, String content)
1840                    throws PortalException, SystemException {
1841    
1842                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1843                            groupId, articleId, version);
1844    
1845                    article.setContent(content);
1846    
1847                    journalArticlePersistence.update(article, false);
1848    
1849                    return article;
1850            }
1851    
1852            public JournalArticle updateStatus(
1853                            long userId, JournalArticle article, int status, String articleURL,
1854                            ServiceContext serviceContext)
1855                    throws PortalException, SystemException {
1856    
1857                    User user = userPersistence.findByPrimaryKey(userId);
1858                    Date now = new Date();
1859    
1860                    int oldStatus = article.getStatus();
1861    
1862                    // Article
1863    
1864                    article.setModifiedDate(serviceContext.getModifiedDate(now));
1865                    article.setStatus(status);
1866                    article.setStatusByUserId(user.getUserId());
1867                    article.setStatusByUserName(user.getFullName());
1868                    article.setStatusDate(serviceContext.getModifiedDate(now));
1869    
1870                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
1871                            (article.getExpirationDate() != null) &&
1872                            (article.getExpirationDate().before(now))) {
1873    
1874                            article.setExpirationDate(null);
1875                    }
1876    
1877                    if (status == WorkflowConstants.STATUS_EXPIRED) {
1878                            article.setExpirationDate(now);
1879                    }
1880    
1881                    journalArticlePersistence.update(article, false);
1882    
1883                    if (isLatestVersion(
1884                                    article.getGroupId(), article.getArticleId(),
1885                                    article.getVersion())) {
1886    
1887                            if (status == WorkflowConstants.STATUS_APPROVED) {
1888                                    updateUrlTitles(
1889                                            article.getGroupId(), article.getArticleId(),
1890                                            article.getUrlTitle());
1891    
1892                                    // Asset
1893    
1894                                    if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
1895                                            (article.getVersion() !=
1896                                                    JournalArticleConstants.DEFAULT_VERSION)) {
1897    
1898                                            AssetEntry draftAssetEntry = null;
1899    
1900                                            try {
1901                                                    draftAssetEntry = assetEntryLocalService.getEntry(
1902                                                            JournalArticle.class.getName(),
1903                                                            article.getPrimaryKey());
1904    
1905                                                    Date[] dateInterval = getDateInterval(
1906                                                            article.getGroupId(), article.getArticleId(),
1907                                                            article.getDisplayDate(),
1908                                                            article.getExpirationDate());
1909    
1910                                                    Date displayDate = dateInterval[0];
1911                                                    Date expirationDate = dateInterval[1];
1912    
1913                                                    long[] assetCategoryIds =
1914                                                            draftAssetEntry.getCategoryIds();
1915                                                    String[] assetTagNames = draftAssetEntry.getTagNames();
1916    
1917                                                    assetEntryLocalService.updateEntry(
1918                                                            userId, article.getGroupId(),
1919                                                            JournalArticle.class.getName(),
1920                                                            article.getResourcePrimKey(), article.getUuid(),
1921                                                            assetCategoryIds, assetTagNames, true, null, null,
1922                                                            displayDate, expirationDate, ContentTypes.TEXT_HTML,
1923                                                            article.getTitle(), article.getDescription(), null,
1924                                                            null, 0, 0, null, false);
1925    
1926                                                    assetEntryLocalService.deleteEntry(
1927                                                            JournalArticle.class.getName(),
1928                                                            article.getPrimaryKey());
1929                                            }
1930                                            catch (NoSuchEntryException nsee) {
1931                                            }
1932                                    }
1933    
1934                                    assetEntryLocalService.updateVisible(
1935                                            JournalArticle.class.getName(),
1936                                            article.getResourcePrimKey(), true);
1937    
1938                                    // Expando
1939    
1940                                    ExpandoBridge expandoBridge = article.getExpandoBridge();
1941    
1942                                    expandoBridge.setAttributes(serviceContext);
1943    
1944                                    // Indexer
1945    
1946                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
1947                                            JournalArticle.class);
1948    
1949                                    indexer.reindex(article);
1950                            }
1951                            else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1952                                    updatePreviousApprovedArticle(article);
1953                            }
1954                    }
1955    
1956                    // Email
1957    
1958                    if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
1959                            ((status == WorkflowConstants.STATUS_APPROVED) ||
1960                             (status == WorkflowConstants.STATUS_DENIED))) {
1961    
1962                            String msg = "granted";
1963    
1964                            if (status == WorkflowConstants.STATUS_DENIED) {
1965                                    msg = "denied";
1966                            }
1967    
1968                            try {
1969                                    PortletPreferences preferences =
1970                                            ServiceContextUtil.getPortletPreferences(serviceContext);
1971    
1972                                    sendEmail(article, articleURL, preferences, msg);
1973                            }
1974                            catch (Exception e) {
1975                                    _log.error(
1976                                            "Unable to send email to notify the change of status " +
1977                                                    " to " + msg + " for article " + article.getId() +
1978                                                            ": " + e.getMessage());
1979                            }
1980                    }
1981    
1982                    // Subscriptions
1983    
1984                    notifySubscribers(article, serviceContext);
1985    
1986                    return article;
1987            }
1988    
1989            public JournalArticle updateStatus(
1990                            long userId, long classPK, int status,
1991                            ServiceContext serviceContext)
1992                    throws PortalException, SystemException {
1993    
1994                    JournalArticle article = getArticle(classPK);
1995    
1996                    return updateStatus(userId, article, status, null, serviceContext);
1997            }
1998    
1999            public JournalArticle updateStatus(
2000                            long userId, long groupId, String articleId, double version,
2001                            int status, String articleURL, ServiceContext serviceContext)
2002                    throws PortalException, SystemException {
2003    
2004                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2005                            groupId, articleId, version);
2006    
2007                    return updateStatus(
2008                            userId, article, status, articleURL, serviceContext);
2009            }
2010    
2011            protected void checkStructure(Document contentDoc, Element root)
2012                    throws PortalException {
2013    
2014                    for (Element el : root.elements()) {
2015                            checkStructureField(el, contentDoc);
2016    
2017                            checkStructure(contentDoc, el);
2018                    }
2019            }
2020    
2021            protected void checkStructure(JournalArticle article)
2022                    throws DocumentException, PortalException, SystemException {
2023    
2024                    JournalStructure structure = journalStructurePersistence.findByG_S(
2025                            article.getGroupId(), article.getStructureId());
2026    
2027                    String content = GetterUtil.getString(article.getContent());
2028    
2029                    Document contentDoc = SAXReaderUtil.read(content);
2030                    Document xsdDoc = SAXReaderUtil.read(structure.getXsd());
2031    
2032                    try {
2033                            checkStructure(contentDoc, xsdDoc.getRootElement());
2034                    }
2035                    catch (StructureXsdException sxsde) {
2036                            long groupId = article.getGroupId();
2037                            String articleId = article.getArticleId();
2038                            double version = article.getVersion();
2039    
2040                            if (_log.isWarnEnabled()) {
2041                                    _log.warn(
2042                                            "Article {groupId=" + groupId + ", articleId=" +
2043                                                    articleId + ", version=" + version +
2044                                                            "} has content that does not match its " +
2045                                                                    "structure: " + sxsde.getMessage());
2046                            }
2047                    }
2048            }
2049    
2050            protected void checkStructureField(Element el, Document contentDoc)
2051                    throws PortalException {
2052    
2053                    StringBuilder elPath = new StringBuilder();
2054    
2055                    elPath.append(el.attributeValue("name"));
2056    
2057                    Element elParent = el.getParent();
2058    
2059                    for (;;) {
2060                            if ((elParent == null) ||
2061                                    (elParent.getName().equals("root"))) {
2062    
2063                                    break;
2064                            }
2065    
2066                            elPath.insert(
2067                                    0, elParent.attributeValue("name") + StringPool.COMMA);
2068    
2069                            elParent = elParent.getParent();
2070                    }
2071    
2072                    String[] elPathNames = StringUtil.split(elPath.toString());
2073    
2074                    Element contentEl = contentDoc.getRootElement();
2075    
2076                    for (String _elPathName : elPathNames) {
2077                            boolean foundEl = false;
2078    
2079                            for (Element tempEl : contentEl.elements()) {
2080                                    if (_elPathName.equals(
2081                                                    tempEl.attributeValue("name", StringPool.BLANK))) {
2082    
2083                                            contentEl = tempEl;
2084                                            foundEl = true;
2085    
2086                                            break;
2087                                    }
2088                            }
2089    
2090                            if (!foundEl) {
2091                                    String elType = contentEl.attributeValue(
2092                                            "type", StringPool.BLANK);
2093    
2094                                    if (!elType.equals("list") && !elType.equals("multi-list")) {
2095                                            throw new StructureXsdException(elPath.toString());
2096                                    }
2097    
2098                                    break;
2099                            }
2100                    }
2101            }
2102    
2103            protected void copyArticleImages(
2104                            JournalArticle oldArticle, JournalArticle newArticle)
2105                    throws Exception {
2106    
2107                    Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
2108    
2109                    XPath xpathSelector = SAXReaderUtil.createXPath(
2110                            "//dynamic-element[@type='image']");
2111    
2112                    List<Node> imageNodes = xpathSelector.selectNodes(contentDoc);
2113    
2114                    for (Node imageNode : imageNodes) {
2115                            Element imageEl = (Element)imageNode;
2116    
2117                            String instanceId = imageEl.attributeValue("instance-id");
2118                            String name = imageEl.attributeValue("name");
2119    
2120                            List<Element> dynamicContentEls = imageEl.elements(
2121                                    "dynamic-content");
2122    
2123                            for (Element dynamicContentEl : dynamicContentEls) {
2124                                    long imageId = GetterUtil.getLong(
2125                                            dynamicContentEl.attributeValue("id"));
2126                                    String languageId = dynamicContentEl.attributeValue(
2127                                            "language-id");
2128    
2129                                    Image oldImage = null;
2130    
2131                                    try {
2132                                            oldImage = imageLocalService.getImage(imageId);
2133                                    }
2134                                    catch (NoSuchImageException nsie) {
2135                                            continue;
2136                                    }
2137    
2138                                    imageId = journalArticleImageLocalService.getArticleImageId(
2139                                            newArticle.getGroupId(), newArticle.getArticleId(),
2140                                            newArticle.getVersion(), instanceId, name, languageId);
2141    
2142                                    imageLocalService.updateImage(imageId, oldImage.getTextObj());
2143    
2144                                    String elContent =
2145                                            "/image/journal/article?img_id=" + imageId + "&t=" +
2146                                                    ImageServletTokenUtil.getToken(imageId);
2147    
2148                                    dynamicContentEl.setText(elContent);
2149                                    dynamicContentEl.addAttribute("id", String.valueOf(imageId));
2150                            }
2151                    }
2152    
2153                    newArticle.setContent(contentDoc.formattedString());
2154            }
2155    
2156            protected void format(
2157                            long groupId, String articleId, double version,
2158                            boolean incrementVersion, Element root, Map<String, byte[]> images)
2159                    throws PortalException, SystemException {
2160    
2161                    for (Element el : root.elements()) {
2162                            String elInstanceId = el.attributeValue(
2163                                    "instance-id", StringPool.BLANK);
2164                            String elName = el.attributeValue("name", StringPool.BLANK);
2165                            String elType = el.attributeValue("type", StringPool.BLANK);
2166    
2167                            if (elType.equals("image")) {
2168                                    formatImage(
2169                                            groupId, articleId, version, incrementVersion, el,
2170                                            elInstanceId, elName, images);
2171                            }
2172                            /*else if (elType.equals("text_area")) {
2173                                    Element dynamicContent = el.element("dynamic-content");
2174    
2175                                    String text = dynamicContent.getText();
2176    
2177                                    // LEP-1594
2178    
2179                                    try {
2180                                            text = ParserUtils.trimTags(
2181                                                    text, new String[] {"script"}, false, true);
2182                                    }
2183                                    catch (ParserException pe) {
2184                                            text = pe.getLocalizedMessage();
2185                                    }
2186                                    catch (UnsupportedEncodingException uee) {
2187                                            text = uee.getLocalizedMessage();
2188                                    }
2189    
2190                                    dynamicContent.setText(text);
2191                            }*/
2192    
2193                            format(groupId, articleId, version, incrementVersion, el, images);
2194                    }
2195            }
2196    
2197            protected String format(
2198                            long groupId, String articleId, double version,
2199                            boolean incrementVersion, String content, String structureId,
2200                            Map<String, byte[]> images)
2201                    throws PortalException, SystemException {
2202    
2203                    if (Validator.isNotNull(structureId)) {
2204                            Document doc = null;
2205    
2206                            try {
2207                                    doc = SAXReaderUtil.read(content);
2208    
2209                                    Element root = doc.getRootElement();
2210    
2211                                    format(
2212                                            groupId, articleId, version, incrementVersion, root,
2213                                            images);
2214    
2215                                    content = JournalUtil.formatXML(doc);
2216                            }
2217                            catch (DocumentException de) {
2218                                    _log.error(de);
2219                            }
2220                            catch (IOException ioe) {
2221                                    _log.error(ioe);
2222                            }
2223                    }
2224    
2225                    content = HtmlUtil.replaceMsWordCharacters(content);
2226    
2227                    return content;
2228            }
2229    
2230            protected void formatImage(
2231                            long groupId, String articleId, double version,
2232                            boolean incrementVersion, Element el, String elInstanceId,
2233                            String elName, Map<String, byte[]> images)
2234                    throws PortalException, SystemException {
2235    
2236                    List<Element> imageContents = el.elements("dynamic-content");
2237    
2238                    for (Element dynamicContent : imageContents) {
2239                            String elLanguage = dynamicContent.attributeValue(
2240                                    "language-id", StringPool.BLANK);
2241    
2242                            if (!elLanguage.equals(StringPool.BLANK)) {
2243                                    elLanguage = "_" + elLanguage;
2244                            }
2245    
2246                            long imageId =
2247                                    journalArticleImageLocalService.getArticleImageId(
2248                                            groupId, articleId, version, elInstanceId, elName,
2249                                            elLanguage);
2250    
2251                            double oldVersion = MathUtil.format(version - 0.1, 1, 1);
2252    
2253                            long oldImageId = 0;
2254    
2255                            if ((oldVersion >= 1) && incrementVersion) {
2256                                    oldImageId =
2257                                            journalArticleImageLocalService.getArticleImageId(
2258                                                    groupId, articleId, oldVersion, elInstanceId, elName,
2259                                                    elLanguage);
2260                            }
2261    
2262                            String elContent =
2263                                    "/image/journal/article?img_id=" + imageId + "&t=" +
2264                                            ImageServletTokenUtil.getToken(imageId);
2265    
2266                            if (dynamicContent.getText().equals("delete")) {
2267                                    dynamicContent.setText(StringPool.BLANK);
2268    
2269                                    imageLocalService.deleteImage(imageId);
2270    
2271                                    String defaultElLanguage = "";
2272    
2273                                    if (!Validator.isNotNull(elLanguage)) {
2274                                            defaultElLanguage =
2275                                                    "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2276                                    }
2277    
2278                                    long defaultImageId =
2279                                            journalArticleImageLocalService.getArticleImageId(
2280                                                    groupId, articleId, version, elInstanceId, elName,
2281                                                    defaultElLanguage);
2282    
2283                                    imageLocalService.deleteImage(defaultImageId);
2284    
2285                                    continue;
2286                            }
2287    
2288                            byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
2289    
2290                            if (bytes != null && (bytes.length > 0)) {
2291                                    dynamicContent.setText(elContent);
2292                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2293    
2294                                    imageLocalService.updateImage(imageId, bytes);
2295    
2296                                    continue;
2297                            }
2298    
2299                            if ((version > JournalArticleConstants.DEFAULT_VERSION) &&
2300                                    (incrementVersion)) {
2301    
2302                                    Image oldImage = null;
2303    
2304                                    if (oldImageId > 0) {
2305                                            oldImage = imageLocalService.getImage(oldImageId);
2306                                    }
2307    
2308                                    if (oldImage != null) {
2309                                            dynamicContent.setText(elContent);
2310                                            dynamicContent.addAttribute("id", String.valueOf(imageId));
2311    
2312                                            bytes = oldImage.getTextObj();
2313    
2314                                            imageLocalService.updateImage(imageId, bytes);
2315                                    }
2316    
2317                                    continue;
2318                            }
2319    
2320                            Image image = imageLocalService.getImage(imageId);
2321    
2322                            if (image != null) {
2323                                    dynamicContent.setText(elContent);
2324                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2325    
2326                                    continue;
2327                            }
2328    
2329                            long contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2330                                    dynamicContent.getText(), "img_id"));
2331    
2332                            if (contentImageId <= 0) {
2333                                    contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2334                                            dynamicContent.getText(), "img_id", false));
2335                            }
2336    
2337                            if (contentImageId > 0) {
2338                                    image = imageLocalService.getImage(contentImageId);
2339    
2340                                    if (image != null) {
2341                                            dynamicContent.addAttribute(
2342                                                    "id", String.valueOf(contentImageId));
2343    
2344                                            continue;
2345                                    }
2346                            }
2347    
2348                            String defaultElLanguage = "";
2349    
2350                            if (!Validator.isNotNull(elLanguage)) {
2351                                    defaultElLanguage =
2352                                            "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2353                            }
2354    
2355                            long defaultImageId =
2356                                    journalArticleImageLocalService.getArticleImageId(
2357                                            groupId, articleId, version, elInstanceId, elName,
2358                                            defaultElLanguage);
2359    
2360                            Image defaultImage = imageLocalService.getImage(defaultImageId);
2361    
2362                            if (defaultImage != null) {
2363                                    dynamicContent.setText(elContent);
2364                                    dynamicContent.addAttribute(
2365                                            "id", String.valueOf(defaultImageId));
2366    
2367                                    bytes = defaultImage.getTextObj();
2368    
2369                                    imageLocalService.updateImage(defaultImageId, bytes);
2370    
2371                                    continue;
2372                            }
2373    
2374                            dynamicContent.setText(StringPool.BLANK);
2375                    }
2376            }
2377    
2378            protected Date[] getDateInterval(
2379                            long groupId, String articleId, Date earliestDisplayDate,
2380                            Date latestExpirationDate)
2381                    throws SystemException {
2382    
2383                    Date[] dateInterval = new Date[2];
2384    
2385                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
2386                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
2387    
2388                    boolean expiringArticle = true;
2389    
2390                    if (latestExpirationDate == null) {
2391                            expiringArticle = false;
2392                    }
2393    
2394                    for (JournalArticle article : articles) {
2395                            if ((earliestDisplayDate == null) ||
2396                                    ((article.getDisplayDate() != null) &&
2397                                     earliestDisplayDate.after(article.getDisplayDate()))) {
2398    
2399                                    earliestDisplayDate = article.getDisplayDate();
2400                            }
2401    
2402                            if (expiringArticle &&
2403                                    ((latestExpirationDate == null) ||
2404                                     ((article.getExpirationDate() != null) &&
2405                                      latestExpirationDate.before(article.getExpirationDate())))) {
2406    
2407                                    latestExpirationDate = article.getExpirationDate();
2408                            }
2409    
2410                            if (expiringArticle && (article.getExpirationDate() == null)) {
2411                                    latestExpirationDate = null;
2412                                    expiringArticle = false;
2413                            }
2414                    }
2415    
2416                    dateInterval[0] = earliestDisplayDate;
2417                    dateInterval[1] = latestExpirationDate;
2418    
2419                    return dateInterval;
2420            }
2421    
2422            protected String getUniqueUrlTitle(
2423                            long id, long groupId, String articleId, String title)
2424                    throws PortalException, SystemException {
2425    
2426                    String urlTitle = JournalUtil.getUrlTitle(id, title);
2427    
2428                    String newUrlTitle = urlTitle;
2429    
2430                    for (int i = 1;; i++) {
2431                            JournalArticle article = null;
2432    
2433                            try {
2434                                    article = getArticleByUrlTitle(groupId, newUrlTitle);
2435                            }
2436                            catch (NoSuchArticleException nsae) {
2437                            }
2438    
2439                            if ((article == null) || article.getArticleId().equals(articleId)) {
2440                                    break;
2441                            }
2442                            else {
2443                                    newUrlTitle = urlTitle + StringPool.DASH + i;
2444                            }
2445                    }
2446    
2447                    return newUrlTitle;
2448            }
2449    
2450            protected void notifySubscribers(
2451                            JournalArticle article, ServiceContext serviceContext)
2452                    throws PortalException, SystemException {
2453    
2454                    if (!article.isApproved()) {
2455                            return;
2456                    }
2457    
2458                    String articleURL = PortalUtil.getControlPanelFullURL(
2459                            serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
2460    
2461                    if (Validator.isNull(articleURL)) {
2462                            return;
2463                    }
2464    
2465                    PortletPreferences preferences =
2466                            ServiceContextUtil.getPortletPreferences(serviceContext);
2467    
2468                    if (preferences == null) {
2469                            long ownerId = article.getGroupId();
2470                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
2471                            long plid = PortletKeys.PREFS_PLID_SHARED;
2472                            String portletId = PortletKeys.JOURNAL;
2473                            String defaultPreferences = null;
2474    
2475                            preferences = portletPreferencesLocalService.getPreferences(
2476                                    article.getCompanyId(), ownerId, ownerType, plid, portletId,
2477                                    defaultPreferences);
2478                    }
2479    
2480                    if ((article.getVersion() == 1.0) &&
2481                            JournalUtil.getEmailArticleAddedEnabled(preferences)) {
2482                    }
2483                    else if ((article.getVersion() != 1.0) &&
2484                                     JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
2485                    }
2486                    else {
2487                            return;
2488                    }
2489    
2490                    Company company = companyPersistence.findByPrimaryKey(
2491                            article.getCompanyId());
2492    
2493                    String emailAddress = StringPool.BLANK;
2494                    String fullName = article.getUserName();
2495    
2496                    try {
2497                            User user = userPersistence.findByPrimaryKey(article.getUserId());
2498    
2499                            emailAddress = user.getEmailAddress();
2500                            fullName = user.getFullName();
2501                    }
2502                    catch (NoSuchUserException nsue) {
2503                    }
2504    
2505                    String portletName = PortalUtil.getPortletTitle(
2506                            PortletKeys.JOURNAL, LocaleUtil.getDefault());
2507    
2508                    String fromName = JournalUtil.getEmailFromName(preferences);
2509                    String fromAddress = JournalUtil.getEmailFromAddress(preferences);
2510    
2511                    fromName = StringUtil.replace(
2512                            fromName,
2513                            new String[] {
2514                                    "[$ARTICLE_ID$]",
2515                                    "[$ARTICLE_TITLE$]",
2516                                    "[$ARTICLE_USER_ADDRESS$]",
2517                                    "[$ARTICLE_USER_NAME$]",
2518                                    "[$ARTICLE_VERSION$]",
2519                                    "[$FROM_ADDRESS$]",
2520                                    "[$FROM_NAME$]",
2521                                    "[$PORTAL_URL$]",
2522                                    "[$PORTLET_NAME$]",
2523                            },
2524                            new String[] {
2525                                    article.getArticleId(),
2526                                    article.getTitle(),
2527                                    emailAddress,
2528                                    fullName,
2529                                    String.valueOf(article.getVersion()),
2530                                    fromAddress,
2531                                    fromName,
2532                                    company.getVirtualHost(),
2533                                    portletName,
2534                            });
2535    
2536                    fromAddress = StringUtil.replace(
2537                            fromAddress,
2538                            new String[] {
2539                                    "[$ARTICLE_ID$]",
2540                                    "[$ARTICLE_TITLE$]",
2541                                    "[$ARTICLE_USER_ADDRESS$]",
2542                                    "[$ARTICLE_USER_NAME$]",
2543                                    "[$ARTICLE_VERSION$]",
2544                                    "[$FROM_ADDRESS$]",
2545                                    "[$FROM_NAME$]",
2546                                    "[$PORTAL_URL$]",
2547                                    "[$PORTLET_NAME$]",
2548                            },
2549                            new String[] {
2550                                    article.getArticleId(),
2551                                    article.getTitle(),
2552                                    emailAddress,
2553                                    fullName,
2554                                    String.valueOf(article.getVersion()),
2555                                    fromAddress,
2556                                    fromName,
2557                                    company.getVirtualHost(),
2558                                    portletName,
2559                            });
2560    
2561                    String subject = null;
2562                    String body = null;
2563    
2564                    if (article.getVersion() == 1.0) {
2565                            subject = JournalUtil.getEmailArticleAddedSubject(preferences);
2566                            body = JournalUtil.getEmailArticleAddedBody(preferences);
2567                    }
2568                    else {
2569                            subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
2570                            body = JournalUtil.getEmailArticleUpdatedBody(preferences);
2571                    }
2572    
2573                    subject = StringUtil.replace(
2574                            subject,
2575                            new String[] {
2576                                    "[$ARTICLE_ID$]",
2577                                    "[$ARTICLE_TITLE$]",
2578                                    "[$ARTICLE_URL$]",
2579                                    "[$ARTICLE_USER_ADDRESS$]",
2580                                    "[$ARTICLE_USER_NAME$]",
2581                                    "[$ARTICLE_VERSION$]",
2582                                    "[$FROM_ADDRESS$]",
2583                                    "[$FROM_NAME$]",
2584                                    "[$PORTAL_URL$]",
2585                                    "[$PORTLET_NAME$]",
2586                            },
2587                            new String[] {
2588                                    article.getArticleId(),
2589                                    article.getTitle(),
2590                                    articleURL,
2591                                    emailAddress,
2592                                    fullName,
2593                                    String.valueOf(article.getVersion()),
2594                                    fromAddress,
2595                                    fromName,
2596                                    company.getVirtualHost(),
2597                                    portletName,
2598                            });
2599    
2600                    body = StringUtil.replace(
2601                            body,
2602                            new String[] {
2603                                    "[$ARTICLE_ID$]",
2604                                    "[$ARTICLE_TITLE$]",
2605                                    "[$ARTICLE_URL$]",
2606                                    "[$ARTICLE_USER_ADDRESS$]",
2607                                    "[$ARTICLE_USER_NAME$]",
2608                                    "[$ARTICLE_VERSION$]",
2609                                    "[$FROM_ADDRESS$]",
2610                                    "[$FROM_NAME$]",
2611                                    "[$PORTAL_URL$]",
2612                                    "[$PORTLET_NAME$]",
2613                            },
2614                            new String[] {
2615                                    article.getArticleId(),
2616                                    article.getTitle(),
2617                                    articleURL,
2618                                    emailAddress,
2619                                    fullName,
2620                                    String.valueOf(article.getVersion()),
2621                                    fromAddress,
2622                                    fromName,
2623                                    company.getVirtualHost(),
2624                                    portletName,
2625                            });
2626    
2627                    Message message = new Message();
2628    
2629                    message.put("companyId", article.getCompanyId());
2630                    message.put("userId", article.getUserId());
2631                    message.put("groupId", article.getGroupId());
2632                    message.put("articleId", article.getArticleId());
2633                    message.put("fromName", fromName);
2634                    message.put("fromAddress", fromAddress);
2635                    message.put("subject", subject);
2636                    message.put("body", body);
2637                    message.put("replyToAddress", fromAddress);
2638                    message.put(
2639                            "mailId",
2640                            JournalUtil.getMailId(company.getMx(), article.getArticleId()));
2641                    message.put("htmlFormat", Boolean.TRUE);
2642    
2643                    MessageBusUtil.sendMessage(DestinationNames.JOURNAL, message);
2644            }
2645    
2646            protected void saveImages(
2647                            boolean smallImage, long smallImageId, File smallFile,
2648                            byte[] smallBytes)
2649                    throws PortalException, SystemException {
2650    
2651                    if (smallImage) {
2652                            if ((smallFile != null) && (smallBytes != null)) {
2653                                    imageLocalService.updateImage(smallImageId, smallBytes);
2654                            }
2655                    }
2656                    else {
2657                            imageLocalService.deleteImage(smallImageId);
2658                    }
2659            }
2660    
2661            protected void sendEmail(
2662                            JournalArticle article, String articleURL,
2663                            PortletPreferences preferences, String emailType)
2664                    throws IOException, PortalException, SystemException {
2665    
2666                    if (preferences == null) {
2667                            return;
2668                    }
2669                    else if (emailType.equals("denied") &&
2670                            JournalUtil.getEmailArticleApprovalDeniedEnabled(preferences)) {
2671                    }
2672                    else if (emailType.equals("granted") &&
2673                                     JournalUtil.getEmailArticleApprovalGrantedEnabled(
2674                                            preferences)) {
2675                    }
2676                    else if (emailType.equals("requested") &&
2677                                     JournalUtil.getEmailArticleApprovalRequestedEnabled(
2678                                            preferences)) {
2679                    }
2680                    else if (emailType.equals("review") &&
2681                                     JournalUtil.getEmailArticleReviewEnabled(preferences)) {
2682                    }
2683                    else {
2684                            return;
2685                    }
2686    
2687                    Company company = companyPersistence.findByPrimaryKey(
2688                            article.getCompanyId());
2689    
2690                    User user = userPersistence.findByPrimaryKey(article.getUserId());
2691    
2692                    articleURL +=
2693                            "&groupId=" + article.getGroupId() + "&articleId=" +
2694                                    article.getArticleId() + "&version=" + article.getVersion();
2695    
2696                    String portletName = PortalUtil.getPortletTitle(
2697                            PortletKeys.JOURNAL, user);
2698    
2699                    String fromName = JournalUtil.getEmailFromName(preferences);
2700                    String fromAddress = JournalUtil.getEmailFromAddress(preferences);
2701    
2702                    String toName = user.getFullName();
2703                    String toAddress = user.getEmailAddress();
2704    
2705                    if (emailType.equals("requested") ||
2706                            emailType.equals("review")) {
2707    
2708                            String tempToName = fromName;
2709                            String tempToAddress = fromAddress;
2710    
2711                            fromName = toName;
2712                            fromAddress = toAddress;
2713    
2714                            toName = tempToName;
2715                            toAddress = tempToAddress;
2716                    }
2717    
2718                    String subject = null;
2719                    String body = null;
2720    
2721                    if (emailType.equals("denied")) {
2722                            subject =
2723                                    JournalUtil.getEmailArticleApprovalDeniedSubject(preferences);
2724                            body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
2725                    }
2726                    else if (emailType.equals("granted")) {
2727                            subject =
2728                                    JournalUtil.getEmailArticleApprovalGrantedSubject(preferences);
2729                            body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
2730                    }
2731                    else if (emailType.equals("requested")) {
2732                            subject =
2733                                    JournalUtil.getEmailArticleApprovalRequestedSubject(
2734                                    preferences);
2735                            body = JournalUtil.getEmailArticleApprovalRequestedBody(
2736                                    preferences);
2737                    }
2738                    else if (emailType.equals("review")) {
2739                            subject = JournalUtil.getEmailArticleReviewSubject(preferences);
2740                            body = JournalUtil.getEmailArticleReviewBody(preferences);
2741                    }
2742    
2743                    subject = StringUtil.replace(
2744                            subject,
2745                            new String[] {
2746                                    "[$ARTICLE_ID$]",
2747                                    "[$ARTICLE_TITLE$]",
2748                                    "[$ARTICLE_URL$]",
2749                                    "[$ARTICLE_USER_NAME$]",
2750                                    "[$ARTICLE_VERSION$]",
2751                                    "[$FROM_ADDRESS$]",
2752                                    "[$FROM_NAME$]",
2753                                    "[$PORTAL_URL$]",
2754                                    "[$PORTLET_NAME$]",
2755                                    "[$TO_ADDRESS$]",
2756                                    "[$TO_NAME$]"
2757                            },
2758                            new String[] {
2759                                    article.getArticleId(),
2760                                    article.getTitle(),
2761                                    articleURL,
2762                                    article.getUserName(),
2763                                    String.valueOf(article.getVersion()),
2764                                    fromAddress,
2765                                    fromName,
2766                                    company.getVirtualHost(),
2767                                    portletName,
2768                                    toAddress,
2769                                    toName,
2770                            });
2771    
2772                    body = StringUtil.replace(
2773                            body,
2774                            new String[] {
2775                                    "[$ARTICLE_ID$]",
2776                                    "[$ARTICLE_TITLE$]",
2777                                    "[$ARTICLE_URL$]",
2778                                    "[$ARTICLE_USER_NAME$]",
2779                                    "[$ARTICLE_VERSION$]",
2780                                    "[$FROM_ADDRESS$]",
2781                                    "[$FROM_NAME$]",
2782                                    "[$PORTAL_URL$]",
2783                                    "[$PORTLET_NAME$]",
2784                                    "[$TO_ADDRESS$]",
2785                                    "[$TO_NAME$]"
2786                            },
2787                            new String[] {
2788                                    article.getArticleId(),
2789                                    article.getTitle(),
2790                                    articleURL,
2791                                    article.getUserName(),
2792                                    String.valueOf(article.getVersion()),
2793                                    fromAddress,
2794                                    fromName,
2795                                    company.getVirtualHost(),
2796                                    portletName,
2797                                    toAddress,
2798                                    toName,
2799                            });
2800    
2801                    InternetAddress from = new InternetAddress(fromAddress, fromName);
2802    
2803                    InternetAddress to = new InternetAddress(toAddress, toName);
2804    
2805                    MailMessage message = new MailMessage(from, to, subject, body, true);
2806    
2807                    mailService.sendEmail(message);
2808            }
2809    
2810            protected void updatePreviousApprovedArticle(JournalArticle article)
2811                    throws PortalException, SystemException {
2812    
2813                    List<JournalArticle> approvedArticles =
2814                            journalArticlePersistence.findByG_A_ST(
2815                                    article.getGroupId(), article.getArticleId(),
2816                                    WorkflowConstants.STATUS_APPROVED, 0, 2);
2817    
2818                    if (approvedArticles.size() > 1) {
2819                            JournalArticle previousApprovedArticle = approvedArticles.get(1);
2820    
2821                            if (article.isIndexable()) {
2822                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
2823                                            JournalArticle.class);
2824    
2825                                    indexer.reindex(previousApprovedArticle);
2826                            }
2827                    }
2828                    else {
2829                            if (article.isIndexable()) {
2830                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
2831                                            JournalArticle.class);
2832    
2833                                    indexer.delete(article);
2834                            }
2835    
2836                            assetEntryLocalService.updateVisible(
2837                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
2838                                    false);
2839                    }
2840            }
2841    
2842            protected void updateUrlTitles(
2843                            long groupId, String articleId, String urlTitle)
2844                    throws SystemException {
2845    
2846                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
2847                            groupId, articleId);
2848    
2849                    for (JournalArticle article : articles) {
2850                            if (!article.getUrlTitle().equals(urlTitle)) {
2851                                    article.setUrlTitle(urlTitle);
2852    
2853                                    journalArticlePersistence.update(article, false);
2854                            }
2855                    }
2856            }
2857    
2858            protected void validate(
2859                            long companyId, long groupId, String articleId,
2860                            boolean autoArticleId, double version, String title, String content,
2861                            String type, String structureId, String templateId,
2862                            boolean smallImage, String smallImageURL, File smallFile,
2863                            byte[] smallBytes)
2864                    throws PortalException, SystemException {
2865    
2866                    if (!autoArticleId) {
2867                            validate(articleId);
2868    
2869                            JournalArticle article = journalArticlePersistence.fetchByG_A_V(
2870                                    groupId, articleId, version);
2871    
2872                            if (article != null) {
2873                                    throw new DuplicateArticleIdException();
2874                            }
2875                    }
2876    
2877                    validate(
2878                            companyId, groupId, title, content, type, structureId, templateId,
2879                            smallImage, smallImageURL, smallFile, smallBytes);
2880            }
2881    
2882            protected void validate(
2883                            long companyId, long groupId, String title, String content,
2884                            String type, String structureId, String templateId,
2885                            boolean smallImage, String smallImageURL, File smallFile,
2886                            byte[] smallBytes)
2887                    throws PortalException, SystemException {
2888    
2889                    if (Validator.isNull(title)) {
2890                            throw new ArticleTitleException();
2891                    }
2892                    else if (Validator.isNull(content)) {
2893                            throw new ArticleContentException();
2894                    }
2895                    else if (Validator.isNull(type)) {
2896                            throw new ArticleTypeException();
2897                    }
2898    
2899                    if (Validator.isNotNull(structureId)) {
2900                            Group companyGroup = groupLocalService.getCompanyGroup(companyId);
2901    
2902                            try {
2903                                    journalStructurePersistence.findByG_S(
2904                                            groupId, structureId);
2905                            }
2906                            catch (NoSuchStructureException nsse) {
2907                                    journalStructurePersistence.findByG_S(
2908                                            companyGroup.getGroupId(), structureId);
2909                            }
2910    
2911                            JournalTemplate template = null;
2912    
2913                            try {
2914                                    template = journalTemplatePersistence.findByG_T(
2915                                            groupId, templateId);
2916                            }
2917                            catch (NoSuchTemplateException nste) {
2918                                    template = journalTemplatePersistence.findByG_T(
2919                                            companyGroup.getGroupId(), templateId);
2920                            }
2921    
2922                            if (!template.getStructureId().equals(structureId)) {
2923                                    throw new NoSuchTemplateException();
2924                            }
2925                    }
2926    
2927                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
2928                            PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
2929    
2930                    if (smallImage && Validator.isNull(smallImageURL) &&
2931                            smallFile != null && smallBytes != null) {
2932    
2933                            String smallImageName = smallFile.getName();
2934    
2935                            if (smallImageName != null) {
2936                                    boolean validSmallImageExtension = false;
2937    
2938                                    for (String _imageExtension : imageExtensions) {
2939                                            if (StringPool.STAR.equals(_imageExtension) ||
2940                                                    StringUtil.endsWith(smallImageName, _imageExtension)) {
2941    
2942                                                    validSmallImageExtension = true;
2943    
2944                                                    break;
2945                                            }
2946                                    }
2947    
2948                                    if (!validSmallImageExtension) {
2949                                            throw new ArticleSmallImageNameException(smallImageName);
2950                                    }
2951                            }
2952    
2953                            long smallImageMaxSize = PrefsPropsUtil.getLong(
2954                                    PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
2955    
2956                            if ((smallImageMaxSize > 0) &&
2957                                    ((smallBytes == null) ||
2958                                            (smallBytes.length > smallImageMaxSize))) {
2959    
2960                                    throw new ArticleSmallImageSizeException();
2961                            }
2962                    }
2963            }
2964    
2965            protected void validate(String articleId) throws PortalException {
2966                    if ((Validator.isNull(articleId)) ||
2967                            (articleId.indexOf(StringPool.SPACE) != -1)) {
2968    
2969                            throw new ArticleIdException();
2970                    }
2971            }
2972    
2973            private static final String _TOKEN_PAGE_BREAK = PropsUtil.get(
2974                    PropsKeys.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
2975    
2976            private long _journalArticleCheckInterval =
2977                    PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
2978    
2979            private static Log _log = LogFactoryUtil.getLog(
2980                    JournalArticleLocalServiceImpl.class);
2981    
2982    }