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