001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.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.CharPool;
033    import com.liferay.portal.kernel.util.ContentTypes;
034    import com.liferay.portal.kernel.util.FileUtil;
035    import com.liferay.portal.kernel.util.GetterUtil;
036    import com.liferay.portal.kernel.util.HtmlUtil;
037    import com.liferay.portal.kernel.util.HttpUtil;
038    import com.liferay.portal.kernel.util.LocaleUtil;
039    import com.liferay.portal.kernel.util.LocalizationUtil;
040    import com.liferay.portal.kernel.util.MathUtil;
041    import com.liferay.portal.kernel.util.OrderByComparator;
042    import com.liferay.portal.kernel.util.PropsKeys;
043    import com.liferay.portal.kernel.util.StringPool;
044    import com.liferay.portal.kernel.util.StringUtil;
045    import com.liferay.portal.kernel.util.Time;
046    import com.liferay.portal.kernel.util.Validator;
047    import com.liferay.portal.kernel.workflow.WorkflowConstants;
048    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
049    import com.liferay.portal.kernel.xml.Document;
050    import com.liferay.portal.kernel.xml.DocumentException;
051    import com.liferay.portal.kernel.xml.Element;
052    import com.liferay.portal.kernel.xml.Node;
053    import com.liferay.portal.kernel.xml.SAXReaderUtil;
054    import com.liferay.portal.kernel.xml.XPath;
055    import com.liferay.portal.model.Company;
056    import com.liferay.portal.model.Group;
057    import com.liferay.portal.model.Image;
058    import com.liferay.portal.model.PortletPreferencesIds;
059    import com.liferay.portal.model.ResourceConstants;
060    import com.liferay.portal.model.User;
061    import com.liferay.portal.service.ServiceContext;
062    import com.liferay.portal.service.ServiceContextUtil;
063    import com.liferay.portal.servlet.filters.cache.CacheUtil;
064    import com.liferay.portal.theme.ThemeDisplay;
065    import com.liferay.portal.util.PortalUtil;
066    import com.liferay.portal.util.PortletKeys;
067    import com.liferay.portal.util.PrefsPropsUtil;
068    import com.liferay.portal.util.PropsUtil;
069    import com.liferay.portal.util.PropsValues;
070    import com.liferay.portlet.asset.NoSuchEntryException;
071    import com.liferay.portlet.asset.model.AssetEntry;
072    import com.liferay.portlet.expando.model.ExpandoBridge;
073    import com.liferay.portlet.journal.ArticleContentException;
074    import com.liferay.portlet.journal.ArticleDisplayDateException;
075    import com.liferay.portlet.journal.ArticleExpirationDateException;
076    import com.liferay.portlet.journal.ArticleIdException;
077    import com.liferay.portlet.journal.ArticleReviewDateException;
078    import com.liferay.portlet.journal.ArticleSmallImageNameException;
079    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
080    import com.liferay.portlet.journal.ArticleTitleException;
081    import com.liferay.portlet.journal.ArticleTypeException;
082    import com.liferay.portlet.journal.ArticleVersionException;
083    import com.liferay.portlet.journal.DuplicateArticleIdException;
084    import com.liferay.portlet.journal.NoSuchArticleException;
085    import com.liferay.portlet.journal.NoSuchArticleResourceException;
086    import com.liferay.portlet.journal.NoSuchStructureException;
087    import com.liferay.portlet.journal.NoSuchTemplateException;
088    import com.liferay.portlet.journal.StructureXsdException;
089    import com.liferay.portlet.journal.model.JournalArticle;
090    import com.liferay.portlet.journal.model.JournalArticleConstants;
091    import com.liferay.portlet.journal.model.JournalArticleDisplay;
092    import com.liferay.portlet.journal.model.JournalStructure;
093    import com.liferay.portlet.journal.model.JournalTemplate;
094    import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
095    import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
096    import com.liferay.portlet.journal.util.JournalUtil;
097    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
098    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
099    import com.liferay.portlet.journalcontent.util.JournalContentUtil;
100    
101    import java.io.File;
102    import java.io.IOException;
103    
104    import java.util.Calendar;
105    import java.util.Date;
106    import java.util.HashSet;
107    import java.util.List;
108    import java.util.Map;
109    import java.util.Set;
110    
111    import javax.mail.internet.InternetAddress;
112    
113    import javax.portlet.PortletPreferences;
114    
115    /**
116     * @author Brian Wing Shun Chan
117     * @author Raymond Augé
118     * @author Bruno Farache
119     */
120    public class JournalArticleLocalServiceImpl
121            extends JournalArticleLocalServiceBaseImpl {
122    
123            public JournalArticle addArticle(
124                            long userId, long groupId, String articleId, boolean autoArticleId,
125                            double version, String title, String description, String content,
126                            String type, String structureId, String templateId,
127                            int displayDateMonth, int displayDateDay, int displayDateYear,
128                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
129                            int expirationDateDay, int expirationDateYear,
130                            int expirationDateHour, int expirationDateMinute,
131                            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
132                            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
133                            boolean neverReview, boolean indexable, boolean smallImage,
134                            String smallImageURL, File smallFile, Map<String, byte[]> images,
135                            String articleURL, ServiceContext serviceContext)
136                    throws PortalException, SystemException {
137    
138                    // Article
139    
140                    User user = userPersistence.findByPrimaryKey(userId);
141                    articleId = articleId.trim().toUpperCase();
142    
143                    Date displayDate = PortalUtil.getDate(
144                            displayDateMonth, displayDateDay, displayDateYear,
145                            displayDateHour, displayDateMinute, user.getTimeZone(),
146                            new ArticleDisplayDateException());
147    
148                    Date expirationDate = null;
149    
150                    if (!neverExpire) {
151                            expirationDate = PortalUtil.getDate(
152                                    expirationDateMonth, expirationDateDay, expirationDateYear,
153                                    expirationDateHour, expirationDateMinute, user.getTimeZone(),
154                                    new ArticleExpirationDateException());
155                    }
156    
157                    Date reviewDate = null;
158    
159                    if (!neverReview) {
160                            reviewDate = PortalUtil.getDate(
161                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
162                                    reviewDateMinute, user.getTimeZone(),
163                                    new ArticleReviewDateException());
164                    }
165    
166                    byte[] smallBytes = null;
167    
168                    try {
169                            smallBytes = FileUtil.getBytes(smallFile);
170                    }
171                    catch (IOException ioe) {
172                    }
173    
174                    Date now = new Date();
175    
176                    validate(
177                            user.getCompanyId(), groupId, articleId, autoArticleId, version,
178                            title, content, type, structureId, templateId, smallImage,
179                            smallImageURL, smallFile, smallBytes);
180    
181                    if (autoArticleId) {
182                            articleId = String.valueOf(counterLocalService.increment());
183                    }
184    
185                    long id = counterLocalService.increment();
186    
187                    long resourcePrimKey =
188                            journalArticleResourceLocalService.getArticleResourcePrimKey(
189                                    serviceContext.getUuid(), groupId, articleId);
190    
191                    JournalArticle article = journalArticlePersistence.create(id);
192    
193                    content = format(
194                            groupId, articleId, version, false, content, structureId, images);
195    
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                            incrementVersion = true;
1667                    }
1668                    else {
1669                            oldArticle = getLatestArticle(
1670                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
1671    
1672                            oldVersion = oldArticle.getVersion();
1673    
1674                            if ((version > 0) && (version != oldVersion)) {
1675                                    throw new ArticleVersionException();
1676                            }
1677    
1678                            if (oldArticle.isApproved() || oldArticle.isExpired()) {
1679                                    incrementVersion = true;
1680                            }
1681                    }
1682    
1683                    JournalArticle article = null;
1684    
1685                    if (incrementVersion) {
1686                            double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
1687    
1688                            long id = counterLocalService.increment();
1689    
1690                            article = journalArticlePersistence.create(id);
1691    
1692                            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1693                            article.setGroupId(oldArticle.getGroupId());
1694                            article.setCompanyId(user.getCompanyId());
1695                            article.setUserId(user.getUserId());
1696                            article.setUserName(user.getFullName());
1697                            article.setCreateDate(serviceContext.getModifiedDate(now));
1698                            article.setArticleId(articleId);
1699                            article.setVersion(newVersion);
1700                            article.setSmallImageId(oldArticle.getSmallImageId());
1701                    }
1702                    else {
1703                            article = oldArticle;
1704                    }
1705    
1706                    content = format(
1707                            groupId, articleId, article.getVersion(), incrementVersion,
1708                            content, structureId, images);
1709    
1710                    article.setModifiedDate(serviceContext.getModifiedDate(now));
1711                    article.setTitle(title);
1712                    article.setUrlTitle(
1713                            getUniqueUrlTitle(article.getId(), groupId, articleId, title));
1714                    article.setDescription(description);
1715                    article.setContent(content);
1716                    article.setType(type);
1717                    article.setStructureId(structureId);
1718                    article.setTemplateId(templateId);
1719                    article.setDisplayDate(displayDate);
1720    
1721                    if (oldArticle.isPending()) {
1722                            article.setStatus(oldArticle.getStatus());
1723                    }
1724                    else if ((expirationDate == null) || expirationDate.after(now)) {
1725                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
1726                    }
1727                    else {
1728                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
1729                    }
1730    
1731                    article.setExpirationDate(expirationDate);
1732                    article.setReviewDate(reviewDate);
1733                    article.setIndexable(indexable);
1734                    article.setSmallImage(smallImage);
1735    
1736                    if (article.getSmallImageId() == 0) {
1737                            article.setSmallImageId(counterLocalService.increment());
1738                    }
1739    
1740                    article.setSmallImageURL(smallImageURL);
1741    
1742                    journalArticlePersistence.update(article, false);
1743    
1744                    // Asset
1745    
1746                    long[] assetCategoryIds = serviceContext.getAssetCategoryIds();
1747                    String[] assetTagNames = serviceContext.getAssetTagNames();
1748    
1749                    updateAsset(userId, article, assetCategoryIds, assetTagNames);
1750    
1751                    // Expando
1752    
1753                    ExpandoBridge expandoBridge = article.getExpandoBridge();
1754    
1755                    expandoBridge.setAttributes(serviceContext);
1756    
1757                    // Small image
1758    
1759                    saveImages(
1760                            smallImage, article.getSmallImageId(), smallFile, smallBytes);
1761    
1762                    // Email
1763    
1764                    PortletPreferences preferences =
1765                            ServiceContextUtil.getPortletPreferences(serviceContext);
1766    
1767                    // Workflow
1768    
1769                    if (serviceContext.getWorkflowAction() ==
1770                                    WorkflowConstants.ACTION_PUBLISH) {
1771    
1772                            try {
1773                                    sendEmail(article, articleURL, preferences, "requested");
1774                            }
1775                            catch (IOException ioe) {
1776                                    throw new SystemException(ioe);
1777                            }
1778    
1779                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
1780                                    user.getCompanyId(), groupId, userId,
1781                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
1782                                    article, serviceContext);
1783                    }
1784    
1785                    return article;
1786            }
1787    
1788            public void updateAsset(
1789                            long userId, JournalArticle article, long[] assetCategoryIds,
1790                            String[] assetTagNames)
1791                    throws PortalException, SystemException {
1792    
1793                    // Get the earliest display date and latest expiration date among
1794                    // all article versions
1795    
1796                    Date[] dateInterval = getDateInterval(
1797                            article.getGroupId(), article.getArticleId(),
1798                            article.getDisplayDate(), article.getExpirationDate());
1799    
1800                    Date displayDate = dateInterval[0];
1801                    Date expirationDate = dateInterval[1];
1802    
1803                    boolean visible = article.isApproved();
1804    
1805                    boolean addDraftAssetEntry = false;
1806    
1807                    if (!article.isApproved() &&
1808                            (article.getVersion() != JournalArticleConstants.DEFAULT_VERSION)) {
1809    
1810                            int approvedArticlesCount =
1811                                    journalArticlePersistence.countByG_A_ST(
1812                                            article.getGroupId(), article.getArticleId(),
1813                                            WorkflowConstants.STATUS_APPROVED);
1814    
1815                            if (approvedArticlesCount > 0) {
1816                                    addDraftAssetEntry = true;
1817                            }
1818                    }
1819    
1820                    if (addDraftAssetEntry) {
1821                            assetEntryLocalService.updateEntry(
1822                                    userId, article.getGroupId(), JournalArticle.class.getName(),
1823                                    article.getPrimaryKey(), article.getUuid(), assetCategoryIds,
1824                                    assetTagNames, false, null, null, displayDate, expirationDate,
1825                                    ContentTypes.TEXT_HTML, article.getTitle(),
1826                                    article.getDescription(), null, null, 0, 0, null, false);
1827                    }
1828                    else {
1829                            assetEntryLocalService.updateEntry(
1830                                    userId, article.getGroupId(), JournalArticle.class.getName(),
1831                                    article.getResourcePrimKey(), article.getUuid(),
1832                                    assetCategoryIds, assetTagNames, visible, null, null,
1833                                    displayDate, expirationDate, ContentTypes.TEXT_HTML,
1834                                    article.getTitle(), article.getDescription(), null, null, 0, 0,
1835                                    null, false);
1836                    }
1837            }
1838    
1839            public JournalArticle updateContent(
1840                            long groupId, String articleId, double version, String content)
1841                    throws PortalException, SystemException {
1842    
1843                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1844                            groupId, articleId, version);
1845    
1846                    article.setContent(content);
1847    
1848                    journalArticlePersistence.update(article, false);
1849    
1850                    return article;
1851            }
1852    
1853            public JournalArticle updateStatus(
1854                            long userId, JournalArticle article, int status, String articleURL,
1855                            ServiceContext serviceContext)
1856                    throws PortalException, SystemException {
1857    
1858                    User user = userPersistence.findByPrimaryKey(userId);
1859                    Date now = new Date();
1860    
1861                    int oldStatus = article.getStatus();
1862    
1863                    // Article
1864    
1865                    article.setModifiedDate(serviceContext.getModifiedDate(now));
1866                    article.setStatus(status);
1867                    article.setStatusByUserId(user.getUserId());
1868                    article.setStatusByUserName(user.getFullName());
1869                    article.setStatusDate(serviceContext.getModifiedDate(now));
1870    
1871                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
1872                            (article.getExpirationDate() != null) &&
1873                            (article.getExpirationDate().before(now))) {
1874    
1875                            article.setExpirationDate(null);
1876                    }
1877    
1878                    if (status == WorkflowConstants.STATUS_EXPIRED) {
1879                            article.setExpirationDate(now);
1880                    }
1881    
1882                    journalArticlePersistence.update(article, false);
1883    
1884                    if (isLatestVersion(
1885                                    article.getGroupId(), article.getArticleId(),
1886                                    article.getVersion())) {
1887    
1888                            if (status == WorkflowConstants.STATUS_APPROVED) {
1889                                    updateUrlTitles(
1890                                            article.getGroupId(), article.getArticleId(),
1891                                            article.getUrlTitle());
1892    
1893                                    // Asset
1894    
1895                                    if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
1896                                            (article.getVersion() !=
1897                                                    JournalArticleConstants.DEFAULT_VERSION)) {
1898    
1899                                            AssetEntry draftAssetEntry = null;
1900    
1901                                            try {
1902                                                    draftAssetEntry = assetEntryLocalService.getEntry(
1903                                                            JournalArticle.class.getName(),
1904                                                            article.getPrimaryKey());
1905    
1906                                                    Date[] dateInterval = getDateInterval(
1907                                                            article.getGroupId(), article.getArticleId(),
1908                                                            article.getDisplayDate(),
1909                                                            article.getExpirationDate());
1910    
1911                                                    Date displayDate = dateInterval[0];
1912                                                    Date expirationDate = dateInterval[1];
1913    
1914                                                    long[] assetCategoryIds =
1915                                                            draftAssetEntry.getCategoryIds();
1916                                                    String[] assetTagNames = draftAssetEntry.getTagNames();
1917    
1918                                                    assetEntryLocalService.updateEntry(
1919                                                            userId, article.getGroupId(),
1920                                                            JournalArticle.class.getName(),
1921                                                            article.getResourcePrimKey(), article.getUuid(),
1922                                                            assetCategoryIds, assetTagNames, true, null, null,
1923                                                            displayDate, expirationDate, ContentTypes.TEXT_HTML,
1924                                                            article.getTitle(), article.getDescription(), null,
1925                                                            null, 0, 0, null, false);
1926    
1927                                                    assetEntryLocalService.deleteEntry(
1928                                                            JournalArticle.class.getName(),
1929                                                            article.getPrimaryKey());
1930                                            }
1931                                            catch (NoSuchEntryException nsee) {
1932                                            }
1933                                    }
1934    
1935                                    assetEntryLocalService.updateVisible(
1936                                            JournalArticle.class.getName(),
1937                                            article.getResourcePrimKey(), true);
1938    
1939                                    // Expando
1940    
1941                                    ExpandoBridge expandoBridge = article.getExpandoBridge();
1942    
1943                                    expandoBridge.setAttributes(serviceContext);
1944    
1945                                    // Indexer
1946    
1947                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
1948                                            JournalArticle.class);
1949    
1950                                    indexer.reindex(article);
1951                            }
1952                            else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1953                                    updatePreviousApprovedArticle(article);
1954                            }
1955                    }
1956    
1957                    // Email
1958    
1959                    if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
1960                            ((status == WorkflowConstants.STATUS_APPROVED) ||
1961                             (status == WorkflowConstants.STATUS_DENIED))) {
1962    
1963                            String msg = "granted";
1964    
1965                            if (status == WorkflowConstants.STATUS_DENIED) {
1966                                    msg = "denied";
1967                            }
1968    
1969                            try {
1970                                    PortletPreferences preferences =
1971                                            ServiceContextUtil.getPortletPreferences(serviceContext);
1972    
1973                                    sendEmail(article, articleURL, preferences, msg);
1974                            }
1975                            catch (Exception e) {
1976                                    _log.error(
1977                                            "Unable to send email to notify the change of status " +
1978                                                    " to " + msg + " for article " + article.getId() +
1979                                                            ": " + e.getMessage());
1980                            }
1981                    }
1982    
1983                    // Subscriptions
1984    
1985                    notifySubscribers(article, serviceContext);
1986    
1987                    return article;
1988            }
1989    
1990            public JournalArticle updateStatus(
1991                            long userId, long classPK, int status,
1992                            ServiceContext serviceContext)
1993                    throws PortalException, SystemException {
1994    
1995                    JournalArticle article = getArticle(classPK);
1996    
1997                    return updateStatus(userId, article, status, null, serviceContext);
1998            }
1999    
2000            public JournalArticle updateStatus(
2001                            long userId, long groupId, String articleId, double version,
2002                            int status, String articleURL, ServiceContext serviceContext)
2003                    throws PortalException, SystemException {
2004    
2005                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2006                            groupId, articleId, version);
2007    
2008                    return updateStatus(
2009                            userId, article, status, articleURL, serviceContext);
2010            }
2011    
2012            protected void checkStructure(Document contentDoc, Element root)
2013                    throws PortalException {
2014    
2015                    for (Element el : root.elements()) {
2016                            checkStructureField(el, contentDoc);
2017    
2018                            checkStructure(contentDoc, el);
2019                    }
2020            }
2021    
2022            protected void checkStructure(JournalArticle article)
2023                    throws DocumentException, PortalException, SystemException {
2024    
2025                    Group companyGroup = groupLocalService.getCompanyGroup(
2026                            article.getCompanyId());
2027    
2028                    JournalStructure structure = null;
2029    
2030                    try {
2031                            structure = journalStructurePersistence.findByG_S(
2032                                    article.getGroupId(), article.getStructureId());
2033                    }
2034                    catch (NoSuchStructureException nsse) {
2035                            structure = journalStructurePersistence.findByG_S(
2036                                    companyGroup.getGroupId(), article.getStructureId());
2037                    }
2038    
2039                    String content = GetterUtil.getString(article.getContent());
2040    
2041                    Document contentDoc = SAXReaderUtil.read(content);
2042                    Document xsdDoc = SAXReaderUtil.read(structure.getXsd());
2043    
2044                    try {
2045                            checkStructure(contentDoc, xsdDoc.getRootElement());
2046                    }
2047                    catch (StructureXsdException sxsde) {
2048                            long groupId = article.getGroupId();
2049                            String articleId = article.getArticleId();
2050                            double version = article.getVersion();
2051    
2052                            if (_log.isWarnEnabled()) {
2053                                    _log.warn(
2054                                            "Article {groupId=" + groupId + ", articleId=" +
2055                                                    articleId + ", version=" + version +
2056                                                            "} has content that does not match its " +
2057                                                                    "structure: " + sxsde.getMessage());
2058                            }
2059                    }
2060            }
2061    
2062            protected void checkStructureField(Element el, Document contentDoc)
2063                    throws PortalException {
2064    
2065                    StringBuilder elPath = new StringBuilder();
2066    
2067                    elPath.append(el.attributeValue("name"));
2068    
2069                    Element elParent = el.getParent();
2070    
2071                    for (;;) {
2072                            if ((elParent == null) ||
2073                                    (elParent.getName().equals("root"))) {
2074    
2075                                    break;
2076                            }
2077    
2078                            elPath.insert(
2079                                    0, elParent.attributeValue("name") + StringPool.COMMA);
2080    
2081                            elParent = elParent.getParent();
2082                    }
2083    
2084                    String[] elPathNames = StringUtil.split(elPath.toString());
2085    
2086                    Element contentEl = contentDoc.getRootElement();
2087    
2088                    for (String _elPathName : elPathNames) {
2089                            boolean foundEl = false;
2090    
2091                            for (Element tempEl : contentEl.elements()) {
2092                                    if (_elPathName.equals(
2093                                                    tempEl.attributeValue("name", StringPool.BLANK))) {
2094    
2095                                            contentEl = tempEl;
2096                                            foundEl = true;
2097    
2098                                            break;
2099                                    }
2100                            }
2101    
2102                            if (!foundEl) {
2103                                    String elType = contentEl.attributeValue(
2104                                            "type", StringPool.BLANK);
2105    
2106                                    if (!elType.equals("list") && !elType.equals("multi-list")) {
2107                                            throw new StructureXsdException(elPath.toString());
2108                                    }
2109    
2110                                    break;
2111                            }
2112                    }
2113            }
2114    
2115            protected void copyArticleImages(
2116                            JournalArticle oldArticle, JournalArticle newArticle)
2117                    throws Exception {
2118    
2119                    Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
2120    
2121                    XPath xpathSelector = SAXReaderUtil.createXPath(
2122                            "//dynamic-element[@type='image']");
2123    
2124                    List<Node> imageNodes = xpathSelector.selectNodes(contentDoc);
2125    
2126                    for (Node imageNode : imageNodes) {
2127                            Element imageEl = (Element)imageNode;
2128    
2129                            String instanceId = imageEl.attributeValue("instance-id");
2130                            String name = imageEl.attributeValue("name");
2131    
2132                            List<Element> dynamicContentEls = imageEl.elements(
2133                                    "dynamic-content");
2134    
2135                            for (Element dynamicContentEl : dynamicContentEls) {
2136                                    long imageId = GetterUtil.getLong(
2137                                            dynamicContentEl.attributeValue("id"));
2138                                    String languageId = dynamicContentEl.attributeValue(
2139                                            "language-id");
2140    
2141                                    Image oldImage = null;
2142    
2143                                    try {
2144                                            oldImage = imageLocalService.getImage(imageId);
2145                                    }
2146                                    catch (NoSuchImageException nsie) {
2147                                            continue;
2148                                    }
2149    
2150                                    imageId = journalArticleImageLocalService.getArticleImageId(
2151                                            newArticle.getGroupId(), newArticle.getArticleId(),
2152                                            newArticle.getVersion(), instanceId, name, languageId);
2153    
2154                                    imageLocalService.updateImage(imageId, oldImage.getTextObj());
2155    
2156                                    String elContent =
2157                                            "/image/journal/article?img_id=" + imageId + "&t=" +
2158                                                    ImageServletTokenUtil.getToken(imageId);
2159    
2160                                    dynamicContentEl.setText(elContent);
2161                                    dynamicContentEl.addAttribute("id", String.valueOf(imageId));
2162                            }
2163                    }
2164    
2165                    newArticle.setContent(contentDoc.formattedString());
2166            }
2167    
2168            protected void format(
2169                            long groupId, String articleId, double version,
2170                            boolean incrementVersion, Element root, Map<String, byte[]> images)
2171                    throws PortalException, SystemException {
2172    
2173                    for (Element el : root.elements()) {
2174                            String elInstanceId = el.attributeValue(
2175                                    "instance-id", StringPool.BLANK);
2176                            String elName = el.attributeValue("name", StringPool.BLANK);
2177                            String elType = el.attributeValue("type", StringPool.BLANK);
2178    
2179                            if (elType.equals("image")) {
2180                                    formatImage(
2181                                            groupId, articleId, version, incrementVersion, el,
2182                                            elInstanceId, elName, images);
2183                            }
2184                            /*else if (elType.equals("text_area")) {
2185                                    Element dynamicContent = el.element("dynamic-content");
2186    
2187                                    String text = dynamicContent.getText();
2188    
2189                                    // LEP-1594
2190    
2191                                    try {
2192                                            text = ParserUtils.trimTags(
2193                                                    text, new String[] {"script"}, false, true);
2194                                    }
2195                                    catch (ParserException pe) {
2196                                            text = pe.getLocalizedMessage();
2197                                    }
2198                                    catch (UnsupportedEncodingException uee) {
2199                                            text = uee.getLocalizedMessage();
2200                                    }
2201    
2202                                    dynamicContent.setText(text);
2203                            }*/
2204    
2205                            format(groupId, articleId, version, incrementVersion, el, images);
2206                    }
2207            }
2208    
2209            protected String format(
2210                            long groupId, String articleId, double version,
2211                            boolean incrementVersion, String content, String structureId,
2212                            Map<String, byte[]> images)
2213                    throws PortalException, SystemException {
2214    
2215                    if (Validator.isNotNull(structureId)) {
2216                            Document doc = null;
2217    
2218                            try {
2219                                    doc = SAXReaderUtil.read(content);
2220    
2221                                    Element root = doc.getRootElement();
2222    
2223                                    format(
2224                                            groupId, articleId, version, incrementVersion, root,
2225                                            images);
2226    
2227                                    content = JournalUtil.formatXML(doc);
2228                            }
2229                            catch (DocumentException de) {
2230                                    _log.error(de);
2231                            }
2232                            catch (IOException ioe) {
2233                                    _log.error(ioe);
2234                            }
2235                    }
2236    
2237                    content = HtmlUtil.replaceMsWordCharacters(content);
2238    
2239                    return content;
2240            }
2241    
2242            protected void formatImage(
2243                            long groupId, String articleId, double version,
2244                            boolean incrementVersion, Element el, String elInstanceId,
2245                            String elName, Map<String, byte[]> images)
2246                    throws PortalException, SystemException {
2247    
2248                    List<Element> imageContents = el.elements("dynamic-content");
2249    
2250                    for (Element dynamicContent : imageContents) {
2251                            String elLanguage = dynamicContent.attributeValue(
2252                                    "language-id", StringPool.BLANK);
2253    
2254                            if (!elLanguage.equals(StringPool.BLANK)) {
2255                                    elLanguage = "_" + elLanguage;
2256                            }
2257    
2258                            long imageId =
2259                                    journalArticleImageLocalService.getArticleImageId(
2260                                            groupId, articleId, version, elInstanceId, elName,
2261                                            elLanguage);
2262    
2263                            double oldVersion = MathUtil.format(version - 0.1, 1, 1);
2264    
2265                            long oldImageId = 0;
2266    
2267                            if ((oldVersion >= 1) && incrementVersion) {
2268                                    oldImageId =
2269                                            journalArticleImageLocalService.getArticleImageId(
2270                                                    groupId, articleId, oldVersion, elInstanceId, elName,
2271                                                    elLanguage);
2272                            }
2273    
2274                            String elContent =
2275                                    "/image/journal/article?img_id=" + imageId + "&t=" +
2276                                            ImageServletTokenUtil.getToken(imageId);
2277    
2278                            if (dynamicContent.getText().equals("delete")) {
2279                                    dynamicContent.setText(StringPool.BLANK);
2280    
2281                                    imageLocalService.deleteImage(imageId);
2282    
2283                                    String defaultElLanguage = "";
2284    
2285                                    if (!Validator.isNotNull(elLanguage)) {
2286                                            defaultElLanguage =
2287                                                    "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2288                                    }
2289    
2290                                    long defaultImageId =
2291                                            journalArticleImageLocalService.getArticleImageId(
2292                                                    groupId, articleId, version, elInstanceId, elName,
2293                                                    defaultElLanguage);
2294    
2295                                    imageLocalService.deleteImage(defaultImageId);
2296    
2297                                    continue;
2298                            }
2299    
2300                            byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
2301    
2302                            if (bytes != null && (bytes.length > 0)) {
2303                                    dynamicContent.setText(elContent);
2304                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2305    
2306                                    imageLocalService.updateImage(imageId, bytes);
2307    
2308                                    continue;
2309                            }
2310    
2311                            if ((version > JournalArticleConstants.DEFAULT_VERSION) &&
2312                                    (incrementVersion)) {
2313    
2314                                    Image oldImage = null;
2315    
2316                                    if (oldImageId > 0) {
2317                                            oldImage = imageLocalService.getImage(oldImageId);
2318                                    }
2319    
2320                                    if (oldImage != null) {
2321                                            dynamicContent.setText(elContent);
2322                                            dynamicContent.addAttribute("id", String.valueOf(imageId));
2323    
2324                                            bytes = oldImage.getTextObj();
2325    
2326                                            imageLocalService.updateImage(imageId, bytes);
2327                                    }
2328    
2329                                    continue;
2330                            }
2331    
2332                            Image image = imageLocalService.getImage(imageId);
2333    
2334                            if (image != null) {
2335                                    dynamicContent.setText(elContent);
2336                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2337    
2338                                    continue;
2339                            }
2340    
2341                            long contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2342                                    dynamicContent.getText(), "img_id"));
2343    
2344                            if (contentImageId <= 0) {
2345                                    contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2346                                            dynamicContent.getText(), "img_id", false));
2347                            }
2348    
2349                            if (contentImageId > 0) {
2350                                    image = imageLocalService.getImage(contentImageId);
2351    
2352                                    if (image != null) {
2353                                            dynamicContent.addAttribute(
2354                                                    "id", String.valueOf(contentImageId));
2355    
2356                                            continue;
2357                                    }
2358                            }
2359    
2360                            String defaultElLanguage = "";
2361    
2362                            if (!Validator.isNotNull(elLanguage)) {
2363                                    defaultElLanguage =
2364                                            "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2365                            }
2366    
2367                            long defaultImageId =
2368                                    journalArticleImageLocalService.getArticleImageId(
2369                                            groupId, articleId, version, elInstanceId, elName,
2370                                            defaultElLanguage);
2371    
2372                            Image defaultImage = imageLocalService.getImage(defaultImageId);
2373    
2374                            if (defaultImage != null) {
2375                                    dynamicContent.setText(elContent);
2376                                    dynamicContent.addAttribute(
2377                                            "id", String.valueOf(defaultImageId));
2378    
2379                                    bytes = defaultImage.getTextObj();
2380    
2381                                    imageLocalService.updateImage(defaultImageId, bytes);
2382    
2383                                    continue;
2384                            }
2385    
2386                            dynamicContent.setText(StringPool.BLANK);
2387                    }
2388            }
2389    
2390            protected Date[] getDateInterval(
2391                            long groupId, String articleId, Date earliestDisplayDate,
2392                            Date latestExpirationDate)
2393                    throws SystemException {
2394    
2395                    Date[] dateInterval = new Date[2];
2396    
2397                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
2398                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
2399    
2400                    boolean expiringArticle = true;
2401    
2402                    if (latestExpirationDate == null) {
2403                            expiringArticle = false;
2404                    }
2405    
2406                    for (JournalArticle article : articles) {
2407                            if ((earliestDisplayDate == null) ||
2408                                    ((article.getDisplayDate() != null) &&
2409                                     earliestDisplayDate.after(article.getDisplayDate()))) {
2410    
2411                                    earliestDisplayDate = article.getDisplayDate();
2412                            }
2413    
2414                            if (expiringArticle &&
2415                                    ((latestExpirationDate == null) ||
2416                                     ((article.getExpirationDate() != null) &&
2417                                      latestExpirationDate.before(article.getExpirationDate())))) {
2418    
2419                                    latestExpirationDate = article.getExpirationDate();
2420                            }
2421    
2422                            if (expiringArticle && (article.getExpirationDate() == null)) {
2423                                    latestExpirationDate = null;
2424                                    expiringArticle = false;
2425                            }
2426                    }
2427    
2428                    dateInterval[0] = earliestDisplayDate;
2429                    dateInterval[1] = latestExpirationDate;
2430    
2431                    return dateInterval;
2432            }
2433    
2434            protected String getUniqueUrlTitle(
2435                            long id, long groupId, String articleId, String title)
2436                    throws PortalException, SystemException {
2437    
2438                    String urlTitle = JournalUtil.getUrlTitle(id, title);
2439    
2440                    String newUrlTitle = urlTitle;
2441    
2442                    for (int i = 1;; i++) {
2443                            JournalArticle article = null;
2444    
2445                            try {
2446                                    article = getArticleByUrlTitle(groupId, newUrlTitle);
2447                            }
2448                            catch (NoSuchArticleException nsae) {
2449                            }
2450    
2451                            if ((article == null) || article.getArticleId().equals(articleId)) {
2452                                    break;
2453                            }
2454                            else {
2455                                    newUrlTitle = urlTitle + StringPool.DASH + i;
2456                            }
2457                    }
2458    
2459                    return newUrlTitle;
2460            }
2461    
2462            protected void notifySubscribers(
2463                            JournalArticle article, ServiceContext serviceContext)
2464                    throws PortalException, SystemException {
2465    
2466                    if (!article.isApproved()) {
2467                            return;
2468                    }
2469    
2470                    String articleURL = PortalUtil.getControlPanelFullURL(
2471                            serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
2472    
2473                    if (Validator.isNull(articleURL)) {
2474                            return;
2475                    }
2476    
2477                    PortletPreferences preferences =
2478                            ServiceContextUtil.getPortletPreferences(serviceContext);
2479    
2480                    if (preferences == null) {
2481                            long ownerId = article.getGroupId();
2482                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
2483                            long plid = PortletKeys.PREFS_PLID_SHARED;
2484                            String portletId = PortletKeys.JOURNAL;
2485                            String defaultPreferences = null;
2486    
2487                            preferences = portletPreferencesLocalService.getPreferences(
2488                                    article.getCompanyId(), ownerId, ownerType, plid, portletId,
2489                                    defaultPreferences);
2490                    }
2491    
2492                    if ((article.getVersion() == 1.0) &&
2493                            JournalUtil.getEmailArticleAddedEnabled(preferences)) {
2494                    }
2495                    else if ((article.getVersion() != 1.0) &&
2496                                     JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
2497                    }
2498                    else {
2499                            return;
2500                    }
2501    
2502                    Company company = companyPersistence.findByPrimaryKey(
2503                            article.getCompanyId());
2504    
2505                    String emailAddress = StringPool.BLANK;
2506                    String fullName = article.getUserName();
2507    
2508                    try {
2509                            User user = userPersistence.findByPrimaryKey(article.getUserId());
2510    
2511                            emailAddress = user.getEmailAddress();
2512                            fullName = user.getFullName();
2513                    }
2514                    catch (NoSuchUserException nsue) {
2515                    }
2516    
2517                    String portletName = PortalUtil.getPortletTitle(
2518                            PortletKeys.JOURNAL, LocaleUtil.getDefault());
2519    
2520                    String fromName = JournalUtil.getEmailFromName(preferences);
2521                    String fromAddress = JournalUtil.getEmailFromAddress(preferences);
2522    
2523                    fromName = StringUtil.replace(
2524                            fromName,
2525                            new String[] {
2526                                    "[$ARTICLE_ID$]",
2527                                    "[$ARTICLE_TITLE$]",
2528                                    "[$ARTICLE_USER_ADDRESS$]",
2529                                    "[$ARTICLE_USER_NAME$]",
2530                                    "[$ARTICLE_VERSION$]",
2531                                    "[$FROM_ADDRESS$]",
2532                                    "[$FROM_NAME$]",
2533                                    "[$PORTAL_URL$]",
2534                                    "[$PORTLET_NAME$]",
2535                            },
2536                            new String[] {
2537                                    article.getArticleId(),
2538                                    article.getTitle(),
2539                                    emailAddress,
2540                                    fullName,
2541                                    String.valueOf(article.getVersion()),
2542                                    fromAddress,
2543                                    fromName,
2544                                    company.getVirtualHost(),
2545                                    portletName,
2546                            });
2547    
2548                    fromAddress = StringUtil.replace(
2549                            fromAddress,
2550                            new String[] {
2551                                    "[$ARTICLE_ID$]",
2552                                    "[$ARTICLE_TITLE$]",
2553                                    "[$ARTICLE_USER_ADDRESS$]",
2554                                    "[$ARTICLE_USER_NAME$]",
2555                                    "[$ARTICLE_VERSION$]",
2556                                    "[$FROM_ADDRESS$]",
2557                                    "[$FROM_NAME$]",
2558                                    "[$PORTAL_URL$]",
2559                                    "[$PORTLET_NAME$]",
2560                            },
2561                            new String[] {
2562                                    article.getArticleId(),
2563                                    article.getTitle(),
2564                                    emailAddress,
2565                                    fullName,
2566                                    String.valueOf(article.getVersion()),
2567                                    fromAddress,
2568                                    fromName,
2569                                    company.getVirtualHost(),
2570                                    portletName,
2571                            });
2572    
2573                    String subject = null;
2574                    String body = null;
2575    
2576                    if (article.getVersion() == 1.0) {
2577                            subject = JournalUtil.getEmailArticleAddedSubject(preferences);
2578                            body = JournalUtil.getEmailArticleAddedBody(preferences);
2579                    }
2580                    else {
2581                            subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
2582                            body = JournalUtil.getEmailArticleUpdatedBody(preferences);
2583                    }
2584    
2585                    subject = StringUtil.replace(
2586                            subject,
2587                            new String[] {
2588                                    "[$ARTICLE_ID$]",
2589                                    "[$ARTICLE_TITLE$]",
2590                                    "[$ARTICLE_URL$]",
2591                                    "[$ARTICLE_USER_ADDRESS$]",
2592                                    "[$ARTICLE_USER_NAME$]",
2593                                    "[$ARTICLE_VERSION$]",
2594                                    "[$FROM_ADDRESS$]",
2595                                    "[$FROM_NAME$]",
2596                                    "[$PORTAL_URL$]",
2597                                    "[$PORTLET_NAME$]",
2598                            },
2599                            new String[] {
2600                                    article.getArticleId(),
2601                                    article.getTitle(),
2602                                    articleURL,
2603                                    emailAddress,
2604                                    fullName,
2605                                    String.valueOf(article.getVersion()),
2606                                    fromAddress,
2607                                    fromName,
2608                                    company.getVirtualHost(),
2609                                    portletName,
2610                            });
2611    
2612                    body = StringUtil.replace(
2613                            body,
2614                            new String[] {
2615                                    "[$ARTICLE_ID$]",
2616                                    "[$ARTICLE_TITLE$]",
2617                                    "[$ARTICLE_URL$]",
2618                                    "[$ARTICLE_USER_ADDRESS$]",
2619                                    "[$ARTICLE_USER_NAME$]",
2620                                    "[$ARTICLE_VERSION$]",
2621                                    "[$FROM_ADDRESS$]",
2622                                    "[$FROM_NAME$]",
2623                                    "[$PORTAL_URL$]",
2624                                    "[$PORTLET_NAME$]",
2625                            },
2626                            new String[] {
2627                                    article.getArticleId(),
2628                                    article.getTitle(),
2629                                    articleURL,
2630                                    emailAddress,
2631                                    fullName,
2632                                    String.valueOf(article.getVersion()),
2633                                    fromAddress,
2634                                    fromName,
2635                                    company.getVirtualHost(),
2636                                    portletName,
2637                            });
2638    
2639                    Message message = new Message();
2640    
2641                    message.put("companyId", article.getCompanyId());
2642                    message.put("userId", article.getUserId());
2643                    message.put("groupId", article.getGroupId());
2644                    message.put("articleId", article.getArticleId());
2645                    message.put("fromName", fromName);
2646                    message.put("fromAddress", fromAddress);
2647                    message.put("subject", subject);
2648                    message.put("body", body);
2649                    message.put("replyToAddress", fromAddress);
2650                    message.put(
2651                            "mailId",
2652                            JournalUtil.getMailId(company.getMx(), article.getArticleId()));
2653                    message.put("htmlFormat", Boolean.TRUE);
2654    
2655                    MessageBusUtil.sendMessage(DestinationNames.JOURNAL, message);
2656            }
2657    
2658            protected void saveImages(
2659                            boolean smallImage, long smallImageId, File smallFile,
2660                            byte[] smallBytes)
2661                    throws PortalException, SystemException {
2662    
2663                    if (smallImage) {
2664                            if ((smallFile != null) && (smallBytes != null)) {
2665                                    imageLocalService.updateImage(smallImageId, smallBytes);
2666                            }
2667                    }
2668                    else {
2669                            imageLocalService.deleteImage(smallImageId);
2670                    }
2671            }
2672    
2673            protected void sendEmail(
2674                            JournalArticle article, String articleURL,
2675                            PortletPreferences preferences, String emailType)
2676                    throws IOException, PortalException, SystemException {
2677    
2678                    if (preferences == null) {
2679                            return;
2680                    }
2681                    else if (emailType.equals("denied") &&
2682                            JournalUtil.getEmailArticleApprovalDeniedEnabled(preferences)) {
2683                    }
2684                    else if (emailType.equals("granted") &&
2685                                     JournalUtil.getEmailArticleApprovalGrantedEnabled(
2686                                            preferences)) {
2687                    }
2688                    else if (emailType.equals("requested") &&
2689                                     JournalUtil.getEmailArticleApprovalRequestedEnabled(
2690                                            preferences)) {
2691                    }
2692                    else if (emailType.equals("review") &&
2693                                     JournalUtil.getEmailArticleReviewEnabled(preferences)) {
2694                    }
2695                    else {
2696                            return;
2697                    }
2698    
2699                    Company company = companyPersistence.findByPrimaryKey(
2700                            article.getCompanyId());
2701    
2702                    User user = userPersistence.findByPrimaryKey(article.getUserId());
2703    
2704                    articleURL +=
2705                            "&groupId=" + article.getGroupId() + "&articleId=" +
2706                                    article.getArticleId() + "&version=" + article.getVersion();
2707    
2708                    String portletName = PortalUtil.getPortletTitle(
2709                            PortletKeys.JOURNAL, user);
2710    
2711                    String fromName = JournalUtil.getEmailFromName(preferences);
2712                    String fromAddress = JournalUtil.getEmailFromAddress(preferences);
2713    
2714                    String toName = user.getFullName();
2715                    String toAddress = user.getEmailAddress();
2716    
2717                    if (emailType.equals("requested") ||
2718                            emailType.equals("review")) {
2719    
2720                            String tempToName = fromName;
2721                            String tempToAddress = fromAddress;
2722    
2723                            fromName = toName;
2724                            fromAddress = toAddress;
2725    
2726                            toName = tempToName;
2727                            toAddress = tempToAddress;
2728                    }
2729    
2730                    String subject = null;
2731                    String body = null;
2732    
2733                    if (emailType.equals("denied")) {
2734                            subject =
2735                                    JournalUtil.getEmailArticleApprovalDeniedSubject(preferences);
2736                            body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
2737                    }
2738                    else if (emailType.equals("granted")) {
2739                            subject =
2740                                    JournalUtil.getEmailArticleApprovalGrantedSubject(preferences);
2741                            body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
2742                    }
2743                    else if (emailType.equals("requested")) {
2744                            subject =
2745                                    JournalUtil.getEmailArticleApprovalRequestedSubject(
2746                                    preferences);
2747                            body = JournalUtil.getEmailArticleApprovalRequestedBody(
2748                                    preferences);
2749                    }
2750                    else if (emailType.equals("review")) {
2751                            subject = JournalUtil.getEmailArticleReviewSubject(preferences);
2752                            body = JournalUtil.getEmailArticleReviewBody(preferences);
2753                    }
2754    
2755                    subject = StringUtil.replace(
2756                            subject,
2757                            new String[] {
2758                                    "[$ARTICLE_ID$]",
2759                                    "[$ARTICLE_TITLE$]",
2760                                    "[$ARTICLE_URL$]",
2761                                    "[$ARTICLE_USER_NAME$]",
2762                                    "[$ARTICLE_VERSION$]",
2763                                    "[$FROM_ADDRESS$]",
2764                                    "[$FROM_NAME$]",
2765                                    "[$PORTAL_URL$]",
2766                                    "[$PORTLET_NAME$]",
2767                                    "[$TO_ADDRESS$]",
2768                                    "[$TO_NAME$]"
2769                            },
2770                            new String[] {
2771                                    article.getArticleId(),
2772                                    article.getTitle(),
2773                                    articleURL,
2774                                    article.getUserName(),
2775                                    String.valueOf(article.getVersion()),
2776                                    fromAddress,
2777                                    fromName,
2778                                    company.getVirtualHost(),
2779                                    portletName,
2780                                    toAddress,
2781                                    toName,
2782                            });
2783    
2784                    body = StringUtil.replace(
2785                            body,
2786                            new String[] {
2787                                    "[$ARTICLE_ID$]",
2788                                    "[$ARTICLE_TITLE$]",
2789                                    "[$ARTICLE_URL$]",
2790                                    "[$ARTICLE_USER_NAME$]",
2791                                    "[$ARTICLE_VERSION$]",
2792                                    "[$FROM_ADDRESS$]",
2793                                    "[$FROM_NAME$]",
2794                                    "[$PORTAL_URL$]",
2795                                    "[$PORTLET_NAME$]",
2796                                    "[$TO_ADDRESS$]",
2797                                    "[$TO_NAME$]"
2798                            },
2799                            new String[] {
2800                                    article.getArticleId(),
2801                                    article.getTitle(),
2802                                    articleURL,
2803                                    article.getUserName(),
2804                                    String.valueOf(article.getVersion()),
2805                                    fromAddress,
2806                                    fromName,
2807                                    company.getVirtualHost(),
2808                                    portletName,
2809                                    toAddress,
2810                                    toName,
2811                            });
2812    
2813                    InternetAddress from = new InternetAddress(fromAddress, fromName);
2814    
2815                    InternetAddress to = new InternetAddress(toAddress, toName);
2816    
2817                    MailMessage message = new MailMessage(from, to, subject, body, true);
2818    
2819                    mailService.sendEmail(message);
2820            }
2821    
2822            protected void updatePreviousApprovedArticle(JournalArticle article)
2823                    throws PortalException, SystemException {
2824    
2825                    List<JournalArticle> approvedArticles =
2826                            journalArticlePersistence.findByG_A_ST(
2827                                    article.getGroupId(), article.getArticleId(),
2828                                    WorkflowConstants.STATUS_APPROVED, 0, 2);
2829    
2830                    if (approvedArticles.size() > 1) {
2831                            JournalArticle previousApprovedArticle = approvedArticles.get(1);
2832    
2833                            if (article.isIndexable()) {
2834                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
2835                                            JournalArticle.class);
2836    
2837                                    indexer.reindex(previousApprovedArticle);
2838                            }
2839                    }
2840                    else {
2841                            if (article.isIndexable()) {
2842                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
2843                                            JournalArticle.class);
2844    
2845                                    indexer.delete(article);
2846                            }
2847    
2848                            assetEntryLocalService.updateVisible(
2849                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
2850                                    false);
2851                    }
2852            }
2853    
2854            protected void updateUrlTitles(
2855                            long groupId, String articleId, String urlTitle)
2856                    throws SystemException {
2857    
2858                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
2859                            groupId, articleId);
2860    
2861                    for (JournalArticle article : articles) {
2862                            if (!article.getUrlTitle().equals(urlTitle)) {
2863                                    article.setUrlTitle(urlTitle);
2864    
2865                                    journalArticlePersistence.update(article, false);
2866                            }
2867                    }
2868            }
2869    
2870            protected void validate(
2871                            long companyId, long groupId, String articleId,
2872                            boolean autoArticleId, double version, String title, String content,
2873                            String type, String structureId, String templateId,
2874                            boolean smallImage, String smallImageURL, File smallFile,
2875                            byte[] smallBytes)
2876                    throws PortalException, SystemException {
2877    
2878                    if (!autoArticleId) {
2879                            validate(articleId);
2880    
2881                            JournalArticle article = journalArticlePersistence.fetchByG_A_V(
2882                                    groupId, articleId, version);
2883    
2884                            if (article != null) {
2885                                    throw new DuplicateArticleIdException();
2886                            }
2887                    }
2888    
2889                    validate(
2890                            companyId, groupId, title, content, type, structureId, templateId,
2891                            smallImage, smallImageURL, smallFile, smallBytes);
2892            }
2893    
2894            protected void validate(
2895                            long companyId, long groupId, String title, String content,
2896                            String type, String structureId, String templateId,
2897                            boolean smallImage, String smallImageURL, File smallFile,
2898                            byte[] smallBytes)
2899                    throws PortalException, SystemException {
2900    
2901                    if (Validator.isNull(title)) {
2902                            throw new ArticleTitleException();
2903                    }
2904                    else if (Validator.isNull(type)) {
2905                            throw new ArticleTypeException();
2906                    }
2907    
2908                    validateContent(content);
2909    
2910                    if (Validator.isNotNull(structureId)) {
2911                            Group companyGroup = groupLocalService.getCompanyGroup(companyId);
2912    
2913                            try {
2914                                    journalStructurePersistence.findByG_S(
2915                                            groupId, structureId);
2916                            }
2917                            catch (NoSuchStructureException nsse) {
2918                                    journalStructurePersistence.findByG_S(
2919                                            companyGroup.getGroupId(), structureId);
2920                            }
2921    
2922                            JournalTemplate template = null;
2923    
2924                            try {
2925                                    template = journalTemplatePersistence.findByG_T(
2926                                            groupId, templateId);
2927                            }
2928                            catch (NoSuchTemplateException nste) {
2929                                    template = journalTemplatePersistence.findByG_T(
2930                                            companyGroup.getGroupId(), templateId);
2931                            }
2932    
2933                            if (!template.getStructureId().equals(structureId)) {
2934                                    throw new NoSuchTemplateException();
2935                            }
2936                    }
2937    
2938                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
2939                            PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
2940    
2941                    if (smallImage && Validator.isNull(smallImageURL) &&
2942                            smallFile != null && smallBytes != null) {
2943    
2944                            String smallImageName = smallFile.getName();
2945    
2946                            if (smallImageName != null) {
2947                                    boolean validSmallImageExtension = false;
2948    
2949                                    for (String _imageExtension : imageExtensions) {
2950                                            if (StringPool.STAR.equals(_imageExtension) ||
2951                                                    StringUtil.endsWith(smallImageName, _imageExtension)) {
2952    
2953                                                    validSmallImageExtension = true;
2954    
2955                                                    break;
2956                                            }
2957                                    }
2958    
2959                                    if (!validSmallImageExtension) {
2960                                            throw new ArticleSmallImageNameException(smallImageName);
2961                                    }
2962                            }
2963    
2964                            long smallImageMaxSize = PrefsPropsUtil.getLong(
2965                                    PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
2966    
2967                            if ((smallImageMaxSize > 0) &&
2968                                    ((smallBytes == null) ||
2969                                            (smallBytes.length > smallImageMaxSize))) {
2970    
2971                                    throw new ArticleSmallImageSizeException();
2972                            }
2973                    }
2974            }
2975    
2976            protected void validate(String articleId) throws PortalException {
2977                    if ((Validator.isNull(articleId)) ||
2978                            (articleId.indexOf(CharPool.SPACE) != -1)) {
2979    
2980                            throw new ArticleIdException();
2981                    }
2982            }
2983    
2984            protected void validateContent(String content) throws PortalException {
2985                    if (Validator.isNull(content)) {
2986                            throw new ArticleContentException();
2987                    }
2988    
2989                    try {
2990                            SAXReaderUtil.read(content);
2991                    }
2992                    catch (DocumentException de) {
2993                            throw new ArticleContentException();
2994                    }
2995            }
2996    
2997            private static final String _TOKEN_PAGE_BREAK = PropsUtil.get(
2998                    PropsKeys.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
2999    
3000            private long _journalArticleCheckInterval =
3001                    PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
3002    
3003            private static Log _log = LogFactoryUtil.getLog(
3004                    JournalArticleLocalServiceImpl.class);
3005    
3006    }