001
014
015 package com.liferay.portlet.journal.service.impl;
016
017 import com.liferay.portal.LocaleException;
018 import com.liferay.portal.NoSuchImageException;
019 import com.liferay.portal.kernel.dao.orm.QueryDefinition;
020 import com.liferay.portal.kernel.dao.orm.QueryUtil;
021 import com.liferay.portal.kernel.exception.PortalException;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.json.JSONFactoryUtil;
024 import com.liferay.portal.kernel.json.JSONObject;
025 import com.liferay.portal.kernel.language.LanguageUtil;
026 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
027 import com.liferay.portal.kernel.log.Log;
028 import com.liferay.portal.kernel.log.LogFactoryUtil;
029 import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
030 import com.liferay.portal.kernel.search.Field;
031 import com.liferay.portal.kernel.search.Hits;
032 import com.liferay.portal.kernel.search.Indexable;
033 import com.liferay.portal.kernel.search.IndexableType;
034 import com.liferay.portal.kernel.search.Indexer;
035 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
036 import com.liferay.portal.kernel.search.QueryConfig;
037 import com.liferay.portal.kernel.search.SearchContext;
038 import com.liferay.portal.kernel.search.SearchException;
039 import com.liferay.portal.kernel.search.Sort;
040 import com.liferay.portal.kernel.util.ArrayUtil;
041 import com.liferay.portal.kernel.util.CalendarFactoryUtil;
042 import com.liferay.portal.kernel.util.CharPool;
043 import com.liferay.portal.kernel.util.ContentTypes;
044 import com.liferay.portal.kernel.util.FileUtil;
045 import com.liferay.portal.kernel.util.GetterUtil;
046 import com.liferay.portal.kernel.util.HtmlUtil;
047 import com.liferay.portal.kernel.util.HttpUtil;
048 import com.liferay.portal.kernel.util.ListUtil;
049 import com.liferay.portal.kernel.util.LocaleUtil;
050 import com.liferay.portal.kernel.util.LocalizationUtil;
051 import com.liferay.portal.kernel.util.MathUtil;
052 import com.liferay.portal.kernel.util.ObjectValuePair;
053 import com.liferay.portal.kernel.util.OrderByComparator;
054 import com.liferay.portal.kernel.util.ParamUtil;
055 import com.liferay.portal.kernel.util.PropsKeys;
056 import com.liferay.portal.kernel.util.StringPool;
057 import com.liferay.portal.kernel.util.StringUtil;
058 import com.liferay.portal.kernel.util.Time;
059 import com.liferay.portal.kernel.util.UnicodeProperties;
060 import com.liferay.portal.kernel.util.Validator;
061 import com.liferay.portal.kernel.workflow.WorkflowConstants;
062 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
063 import com.liferay.portal.kernel.xml.Document;
064 import com.liferay.portal.kernel.xml.DocumentException;
065 import com.liferay.portal.kernel.xml.Element;
066 import com.liferay.portal.kernel.xml.Node;
067 import com.liferay.portal.kernel.xml.SAXReaderUtil;
068 import com.liferay.portal.kernel.xml.XPath;
069 import com.liferay.portal.model.Company;
070 import com.liferay.portal.model.Group;
071 import com.liferay.portal.model.Image;
072 import com.liferay.portal.model.ResourceConstants;
073 import com.liferay.portal.model.User;
074 import com.liferay.portal.service.ServiceContext;
075 import com.liferay.portal.service.ServiceContextUtil;
076 import com.liferay.portal.servlet.filters.cache.CacheUtil;
077 import com.liferay.portal.theme.ThemeDisplay;
078 import com.liferay.portal.util.PortalUtil;
079 import com.liferay.portal.util.PortletKeys;
080 import com.liferay.portal.util.PrefsPropsUtil;
081 import com.liferay.portal.util.PropsValues;
082 import com.liferay.portal.util.SubscriptionSender;
083 import com.liferay.portal.webserver.WebServerServletTokenUtil;
084 import com.liferay.portlet.asset.NoSuchEntryException;
085 import com.liferay.portlet.asset.model.AssetEntry;
086 import com.liferay.portlet.asset.model.AssetLink;
087 import com.liferay.portlet.asset.model.AssetLinkConstants;
088 import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
089 import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
090 import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
091 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
092 import com.liferay.portlet.dynamicdatamapping.storage.FieldConstants;
093 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
094 import com.liferay.portlet.journal.ArticleContentException;
095 import com.liferay.portlet.journal.ArticleDisplayDateException;
096 import com.liferay.portlet.journal.ArticleExpirationDateException;
097 import com.liferay.portlet.journal.ArticleIdException;
098 import com.liferay.portlet.journal.ArticleReviewDateException;
099 import com.liferay.portlet.journal.ArticleSmallImageNameException;
100 import com.liferay.portlet.journal.ArticleSmallImageSizeException;
101 import com.liferay.portlet.journal.ArticleTitleException;
102 import com.liferay.portlet.journal.ArticleTypeException;
103 import com.liferay.portlet.journal.ArticleVersionException;
104 import com.liferay.portlet.journal.DuplicateArticleIdException;
105 import com.liferay.portlet.journal.NoSuchArticleException;
106 import com.liferay.portlet.journal.NoSuchArticleResourceException;
107 import com.liferay.portlet.journal.StructureXsdException;
108 import com.liferay.portlet.journal.model.JournalArticle;
109 import com.liferay.portlet.journal.model.JournalArticleConstants;
110 import com.liferay.portlet.journal.model.JournalArticleDisplay;
111 import com.liferay.portlet.journal.model.JournalArticleResource;
112 import com.liferay.portlet.journal.model.JournalFolder;
113 import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
114 import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
115 import com.liferay.portlet.journal.social.JournalActivityKeys;
116 import com.liferay.portlet.journal.util.JournalUtil;
117 import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
118 import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
119 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
120 import com.liferay.portlet.social.model.SocialActivityConstants;
121 import com.liferay.portlet.trash.model.TrashEntry;
122 import com.liferay.portlet.trash.model.TrashVersion;
123 import com.liferay.portlet.trash.util.TrashUtil;
124
125 import java.io.File;
126 import java.io.IOException;
127 import java.io.Serializable;
128
129 import java.util.ArrayList;
130 import java.util.Calendar;
131 import java.util.Date;
132 import java.util.HashMap;
133 import java.util.HashSet;
134 import java.util.LinkedHashMap;
135 import java.util.List;
136 import java.util.Locale;
137 import java.util.Map;
138 import java.util.Set;
139
140 import javax.portlet.PortletPreferences;
141
142
169 public class JournalArticleLocalServiceImpl
170 extends JournalArticleLocalServiceBaseImpl {
171
172
255 public JournalArticle addArticle(
256 long userId, long groupId, long folderId, long classNameId,
257 long classPK, String articleId, boolean autoArticleId,
258 double version, Map<Locale, String> titleMap,
259 Map<Locale, String> descriptionMap, String content, String type,
260 String ddmStructureKey, String ddmTemplateKey, String layoutUuid,
261 int displayDateMonth, int displayDateDay, int displayDateYear,
262 int displayDateHour, int displayDateMinute, int expirationDateMonth,
263 int expirationDateDay, int expirationDateYear,
264 int expirationDateHour, int expirationDateMinute,
265 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
266 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
267 boolean neverReview, boolean indexable, boolean smallImage,
268 String smallImageURL, File smallImageFile,
269 Map<String, byte[]> images, String articleURL,
270 ServiceContext serviceContext)
271 throws PortalException, SystemException {
272
273
274
275 User user = userPersistence.findByPrimaryKey(userId);
276 articleId = articleId.trim().toUpperCase();
277
278 Date displayDate = null;
279 Date expirationDate = null;
280 Date reviewDate = null;
281
282 if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
283 displayDate = PortalUtil.getDate(
284 displayDateMonth, displayDateDay, displayDateYear,
285 displayDateHour, displayDateMinute, user.getTimeZone(),
286 ArticleDisplayDateException.class);
287
288 if (!neverExpire) {
289 expirationDate = PortalUtil.getDate(
290 expirationDateMonth, expirationDateDay, expirationDateYear,
291 expirationDateHour, expirationDateMinute,
292 user.getTimeZone(), ArticleExpirationDateException.class);
293 }
294
295 if (!neverReview) {
296 reviewDate = PortalUtil.getDate(
297 reviewDateMonth, reviewDateDay, reviewDateYear,
298 reviewDateHour, reviewDateMinute, user.getTimeZone(),
299 ArticleReviewDateException.class);
300 }
301 }
302
303 byte[] smallImageBytes = null;
304
305 try {
306 smallImageBytes = FileUtil.getBytes(smallImageFile);
307 }
308 catch (IOException ioe) {
309 }
310
311 Date now = new Date();
312
313 validate(
314 user.getCompanyId(), groupId, classNameId, articleId, autoArticleId,
315 version, titleMap, content, type, ddmStructureKey, ddmTemplateKey,
316 expirationDate, smallImage, smallImageURL, smallImageFile,
317 smallImageBytes);
318
319 if (autoArticleId) {
320 articleId = String.valueOf(counterLocalService.increment());
321 }
322
323 long id = counterLocalService.increment();
324
325 long resourcePrimKey =
326 journalArticleResourceLocalService.getArticleResourcePrimKey(
327 serviceContext.getUuid(), groupId, articleId);
328
329 JournalArticle article = journalArticlePersistence.create(id);
330
331 Locale locale = LocaleUtil.getDefault();
332
333 String defaultLanguageId = ParamUtil.getString(
334 serviceContext, "defaultLanguageId");
335
336 if (Validator.isNull(defaultLanguageId)) {
337 defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
338 }
339
340 if (Validator.isNotNull(defaultLanguageId)) {
341 locale = LocaleUtil.fromLanguageId(defaultLanguageId);
342 }
343
344 String title = titleMap.get(locale);
345
346 content = format(
347 user, groupId, articleId, version, false, content, ddmStructureKey,
348 images);
349
350 article.setResourcePrimKey(resourcePrimKey);
351 article.setGroupId(groupId);
352 article.setCompanyId(user.getCompanyId());
353 article.setUserId(user.getUserId());
354 article.setUserName(user.getFullName());
355 article.setCreateDate(serviceContext.getCreateDate(now));
356 article.setModifiedDate(serviceContext.getModifiedDate(now));
357 article.setFolderId(folderId);
358 article.setClassNameId(classNameId);
359 article.setClassPK(classPK);
360 article.setArticleId(articleId);
361 article.setVersion(version);
362 article.setTitleMap(titleMap, locale);
363 article.setUrlTitle(
364 getUniqueUrlTitle(id, articleId, title, null, serviceContext));
365 article.setDescriptionMap(descriptionMap, locale);
366 article.setContent(content);
367 article.setType(type);
368 article.setStructureId(ddmStructureKey);
369 article.setTemplateId(ddmTemplateKey);
370 article.setLayoutUuid(layoutUuid);
371 article.setDisplayDate(displayDate);
372 article.setExpirationDate(expirationDate);
373 article.setReviewDate(reviewDate);
374 article.setIndexable(indexable);
375 article.setSmallImage(smallImage);
376 article.setSmallImageId(counterLocalService.increment());
377 article.setSmallImageURL(smallImageURL);
378
379 if ((expirationDate == null) || expirationDate.after(now)) {
380 article.setStatus(WorkflowConstants.STATUS_DRAFT);
381 }
382 else {
383 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
384 }
385
386 article.setExpandoBridgeAttributes(serviceContext);
387
388 journalArticlePersistence.update(article);
389
390
391
392 if (serviceContext.isAddGroupPermissions() ||
393 serviceContext.isAddGuestPermissions()) {
394
395 addArticleResources(
396 article, serviceContext.isAddGroupPermissions(),
397 serviceContext.isAddGuestPermissions());
398 }
399 else {
400 addArticleResources(
401 article, serviceContext.getGroupPermissions(),
402 serviceContext.getGuestPermissions());
403 }
404
405
406
407 saveImages(
408 smallImage, article.getSmallImageId(), smallImageFile,
409 smallImageBytes);
410
411
412
413 updateAsset(
414 userId, article, serviceContext.getAssetCategoryIds(),
415 serviceContext.getAssetTagNames(),
416 serviceContext.getAssetLinkEntryIds());
417
418
419
420 if (PortalUtil.getClassNameId(DDMStructure.class) == classNameId) {
421 updateDDMStructureXSD(classPK, content, serviceContext);
422 }
423
424
425
426 if (PropsValues.JOURNAL_ARTICLE_COMMENTS_ENABLED) {
427 mbMessageLocalService.addDiscussionMessage(
428 userId, article.getUserName(), groupId,
429 JournalArticle.class.getName(), resourcePrimKey,
430 WorkflowConstants.ACTION_PUBLISH);
431 }
432
433
434
435 PortletPreferences preferences =
436 ServiceContextUtil.getPortletPreferences(serviceContext);
437
438 sendEmail(
439 article, articleURL, preferences, "requested", serviceContext);
440
441
442
443 if (classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
444 WorkflowHandlerRegistryUtil.startWorkflowInstance(
445 user.getCompanyId(), groupId, userId,
446 JournalArticle.class.getName(), article.getId(), article,
447 serviceContext);
448
449 if (serviceContext.getWorkflowAction() !=
450 WorkflowConstants.ACTION_PUBLISH) {
451
452
453
454 reindex(article);
455 }
456 }
457 else {
458 updateStatus(
459 userId, article, WorkflowConstants.STATUS_APPROVED, null,
460 new HashMap<String, Serializable>(), serviceContext);
461 }
462
463 return getArticle(article.getPrimaryKey());
464 }
465
466
495 public JournalArticle addArticle(
496 long userId, long groupId, long folderId,
497 Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
498 String content, String ddmStructureKey, String ddmTemplateKey,
499 ServiceContext serviceContext)
500 throws PortalException, SystemException {
501
502 Calendar calendar = CalendarFactoryUtil.getCalendar();
503
504 int displayDateMonth = calendar.get(Calendar.MONTH);
505 int displayDateDay = calendar.get(Calendar.DAY_OF_MONTH);
506 int displayDateYear = calendar.get(Calendar.YEAR);
507 int displayDateHour = calendar.get(Calendar.HOUR_OF_DAY);
508 int displayDateMinute = calendar.get(Calendar.MINUTE);
509
510 return addArticle(
511 userId, groupId, folderId,
512 JournalArticleConstants.CLASSNAME_ID_DEFAULT, 0, StringPool.BLANK,
513 true, 1, titleMap, descriptionMap, content, "general",
514 ddmStructureKey, ddmTemplateKey, null, displayDateMonth,
515 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
516 0, 0, 0, 0, 0, true, 0, 0, 0, 0, 0, true, true, false, null, null,
517 null, null, serviceContext);
518 }
519
520
530 public void addArticleResources(
531 JournalArticle article, boolean addGroupPermissions,
532 boolean addGuestPermissions)
533 throws PortalException, SystemException {
534
535 resourceLocalService.addResources(
536 article.getCompanyId(), article.getGroupId(), article.getUserId(),
537 JournalArticle.class.getName(), article.getResourcePrimKey(), false,
538 addGroupPermissions, addGuestPermissions);
539 }
540
541
550 public void addArticleResources(
551 JournalArticle article, String[] groupPermissions,
552 String[] guestPermissions)
553 throws PortalException, SystemException {
554
555 resourceLocalService.addModelResources(
556 article.getCompanyId(), article.getGroupId(), article.getUserId(),
557 JournalArticle.class.getName(), article.getResourcePrimKey(),
558 groupPermissions, guestPermissions);
559 }
560
561
571 public void addArticleResources(
572 long groupId, String articleId, boolean addGroupPermissions,
573 boolean addGuestPermissions)
574 throws PortalException, SystemException {
575
576 JournalArticle article = getLatestArticle(groupId, articleId);
577
578 addArticleResources(article, addGroupPermissions, addGuestPermissions);
579 }
580
581
592 public void addArticleResources(
593 long groupId, String articleId, String[] groupPermissions,
594 String[] guestPermissions)
595 throws PortalException, SystemException {
596
597 JournalArticle article = getLatestArticle(groupId, articleId);
598
599 addArticleResources(article, groupPermissions, guestPermissions);
600 }
601
602
615 public JournalArticle checkArticleResourcePrimKey(
616 long groupId, String articleId, double version)
617 throws PortalException, SystemException {
618
619 JournalArticle article = journalArticlePersistence.findByG_A_V(
620 groupId, articleId, version);
621
622 if (article.getResourcePrimKey() > 0) {
623 return article;
624 }
625
626 long resourcePrimKey =
627 journalArticleResourceLocalService.getArticleResourcePrimKey(
628 groupId, articleId);
629
630 article.setResourcePrimKey(resourcePrimKey);
631
632 journalArticlePersistence.update(article);
633
634 return article;
635 }
636
637
644 public void checkArticles() throws PortalException, SystemException {
645 Date now = new Date();
646
647 List<JournalArticle> articles =
648 journalArticleFinder.findByExpirationDate(
649 JournalArticleConstants.CLASSNAME_ID_DEFAULT,
650 new Date(now.getTime() + _JOURNAL_ARTICLE_CHECK_INTERVAL),
651 new QueryDefinition(WorkflowConstants.STATUS_APPROVED));
652
653 if (_log.isDebugEnabled()) {
654 _log.debug("Expiring " + articles.size() + " articles");
655 }
656
657 Set<Long> companyIds = new HashSet<Long>();
658
659 for (JournalArticle article : articles) {
660 if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
661 List<JournalArticle> currentArticles =
662 journalArticlePersistence.findByG_A(
663 article.getGroupId(), article.getArticleId(),
664 QueryUtil.ALL_POS, QueryUtil.ALL_POS,
665 new ArticleVersionComparator(true));
666
667 for (JournalArticle currentArticle : currentArticles) {
668 currentArticle.setExpirationDate(
669 article.getExpirationDate());
670 currentArticle.setStatus(WorkflowConstants.STATUS_EXPIRED);
671
672 journalArticlePersistence.update(currentArticle);
673 }
674 }
675 else {
676 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
677
678 journalArticlePersistence.update(article);
679 }
680
681 updatePreviousApprovedArticle(article);
682
683 JournalContentUtil.clearCache(
684 article.getGroupId(), article.getArticleId(),
685 article.getTemplateId());
686
687 companyIds.add(article.getCompanyId());
688 }
689
690 for (long companyId : companyIds) {
691 CacheUtil.clearCache(companyId);
692 }
693
694 if (_previousCheckDate == null) {
695 _previousCheckDate = new Date(
696 now.getTime() - _JOURNAL_ARTICLE_CHECK_INTERVAL);
697 }
698
699 articles = journalArticleFinder.findByReviewDate(
700 JournalArticleConstants.CLASSNAME_ID_DEFAULT, now,
701 _previousCheckDate);
702
703 if (_log.isDebugEnabled()) {
704 _log.debug(
705 "Sending review notifications for " + articles.size() +
706 " articles");
707 }
708
709 for (JournalArticle article : articles) {
710 String articleURL = StringPool.BLANK;
711
712 long ownerId = article.getGroupId();
713 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
714 long plid = PortletKeys.PREFS_PLID_SHARED;
715 String portletId = PortletKeys.JOURNAL;
716
717 PortletPreferences preferences =
718 portletPreferencesLocalService.getPreferences(
719 article.getCompanyId(), ownerId, ownerType, plid,
720 portletId);
721
722 sendEmail(
723 article, articleURL, preferences, "review",
724 new ServiceContext());
725 }
726
727 _previousCheckDate = now;
728 }
729
730
742 public void checkNewLine(long groupId, String articleId, double version)
743 throws PortalException, SystemException {
744
745 JournalArticle article = journalArticlePersistence.findByG_A_V(
746 groupId, articleId, version);
747
748 String content = GetterUtil.getString(article.getContent());
749
750 if (content.contains("\\n")) {
751 content = StringUtil.replace(
752 content, new String[] {"\\n", "\\r"},
753 new String[] {"\n", "\r"});
754
755 article.setContent(content);
756
757 journalArticlePersistence.update(article);
758 }
759 }
760
761
774 public void checkStructure(long groupId, String articleId, double version)
775 throws PortalException, SystemException {
776
777 JournalArticle article = journalArticlePersistence.findByG_A_V(
778 groupId, articleId, version);
779
780 if (Validator.isNull(article.getStructureId())) {
781 return;
782 }
783
784 checkStructure(article);
785 }
786
787
803 public JournalArticle copyArticle(
804 long userId, long groupId, String oldArticleId, String newArticleId,
805 boolean autoArticleId, double version)
806 throws PortalException, SystemException {
807
808
809
810 User user = userPersistence.findByPrimaryKey(userId);
811 oldArticleId = oldArticleId.trim().toUpperCase();
812 newArticleId = newArticleId.trim().toUpperCase();
813 Date now = new Date();
814
815 JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
816 groupId, oldArticleId, version);
817
818 if (autoArticleId) {
819 newArticleId = String.valueOf(counterLocalService.increment());
820 }
821 else {
822 validate(newArticleId);
823
824 if (journalArticlePersistence.countByG_A(
825 groupId, newArticleId) > 0) {
826
827 throw new DuplicateArticleIdException();
828 }
829 }
830
831 long id = counterLocalService.increment();
832
833 long resourcePrimKey =
834 journalArticleResourceLocalService.getArticleResourcePrimKey(
835 groupId, newArticleId);
836
837 JournalArticle newArticle = journalArticlePersistence.create(id);
838
839 newArticle.setResourcePrimKey(resourcePrimKey);
840 newArticle.setGroupId(groupId);
841 newArticle.setCompanyId(user.getCompanyId());
842 newArticle.setUserId(user.getUserId());
843 newArticle.setUserName(user.getFullName());
844 newArticle.setCreateDate(now);
845 newArticle.setModifiedDate(now);
846 newArticle.setArticleId(newArticleId);
847 newArticle.setVersion(JournalArticleConstants.VERSION_DEFAULT);
848 newArticle.setTitle(oldArticle.getTitle());
849 newArticle.setUrlTitle(
850 getUniqueUrlTitle(
851 id, groupId, newArticleId, oldArticle.getTitleCurrentValue()));
852 newArticle.setDescription(oldArticle.getDescription());
853
854 try {
855 copyArticleImages(oldArticle, newArticle);
856 }
857 catch (Exception e) {
858 newArticle.setContent(oldArticle.getContent());
859 }
860
861 newArticle.setType(oldArticle.getType());
862 newArticle.setStructureId(oldArticle.getStructureId());
863 newArticle.setTemplateId(oldArticle.getTemplateId());
864 newArticle.setLayoutUuid(oldArticle.getLayoutUuid());
865 newArticle.setDisplayDate(oldArticle.getDisplayDate());
866 newArticle.setExpirationDate(oldArticle.getExpirationDate());
867 newArticle.setReviewDate(oldArticle.getReviewDate());
868 newArticle.setIndexable(oldArticle.isIndexable());
869 newArticle.setSmallImage(oldArticle.isSmallImage());
870 newArticle.setSmallImageId(counterLocalService.increment());
871 newArticle.setSmallImageURL(oldArticle.getSmallImageURL());
872
873 if (oldArticle.isPending()) {
874 newArticle.setStatus(WorkflowConstants.STATUS_DRAFT);
875 }
876 else {
877 newArticle.setStatus(oldArticle.getStatus());
878 }
879
880 newArticle.setExpandoBridgeAttributes(oldArticle);
881
882 journalArticlePersistence.update(newArticle);
883
884
885
886 addArticleResources(newArticle, true, true);
887
888
889
890 if (oldArticle.getSmallImage()) {
891 Image image = imageLocalService.getImage(
892 oldArticle.getSmallImageId());
893
894 byte[] smallImageBytes = image.getTextObj();
895
896 imageLocalService.updateImage(
897 newArticle.getSmallImageId(), smallImageBytes);
898 }
899
900
901
902 long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
903 JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
904 String[] assetTagNames = assetTagLocalService.getTagNames(
905 JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
906
907 updateAsset(userId, newArticle, assetCategoryIds, assetTagNames, null);
908
909 return newArticle;
910 }
911
912
919 public void deleteArticle(JournalArticle article)
920 throws PortalException, SystemException {
921
922 deleteArticle(article, StringPool.BLANK, null);
923 }
924
925
939 public void deleteArticle(
940 JournalArticle article, String articleURL,
941 ServiceContext serviceContext)
942 throws PortalException, SystemException {
943
944 if (article.isApproved() &&
945 isLatestVersion(
946 article.getGroupId(), article.getArticleId(),
947 article.getVersion(), WorkflowConstants.STATUS_APPROVED)) {
948
949 updatePreviousApprovedArticle(article);
950 }
951 else if (article.isInTrash()) {
952 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
953 JournalArticle.class);
954
955 indexer.delete(article);
956 }
957
958
959
960 if ((serviceContext != null) && Validator.isNotNull(articleURL)) {
961 PortletPreferences preferences =
962 ServiceContextUtil.getPortletPreferences(serviceContext);
963
964 if ((preferences != null) && !article.isApproved() &&
965 isLatestVersion(
966 article.getGroupId(), article.getArticleId(),
967 article.getVersion())) {
968
969 sendEmail(
970 article, articleURL, preferences, "denied", serviceContext);
971 }
972 }
973
974
975
976 journalArticleImageLocalService.deleteImages(
977 article.getGroupId(), article.getArticleId(), article.getVersion());
978
979
980
981 if (!article.isDraft()) {
982 workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
983 article.getCompanyId(), article.getGroupId(),
984 JournalArticle.class.getName(), article.getId());
985 }
986
987 int articlesCount = journalArticlePersistence.countByG_A(
988 article.getGroupId(), article.getArticleId());
989
990 if (articlesCount == 1) {
991
992
993
994 subscriptionLocalService.deleteSubscriptions(
995 article.getCompanyId(), JournalArticle.class.getName(),
996 article.getResourcePrimKey());
997
998
999
1000 ratingsStatsLocalService.deleteStats(
1001 JournalArticle.class.getName(), article.getResourcePrimKey());
1002
1003
1004
1005 mbMessageLocalService.deleteDiscussionMessages(
1006 JournalArticle.class.getName(), article.getResourcePrimKey());
1007
1008
1009
1010 assetEntryLocalService.deleteEntry(
1011 JournalArticle.class.getName(), article.getResourcePrimKey());
1012
1013
1014
1015 journalContentSearchLocalService.deleteArticleContentSearches(
1016 article.getGroupId(), article.getArticleId());
1017
1018
1019
1020 imageLocalService.deleteImage(article.getSmallImageId());
1021
1022
1023
1024 expandoValueLocalService.deleteValues(
1025 JournalArticle.class.getName(), article.getId());
1026
1027
1028
1029 trashEntryLocalService.deleteEntry(
1030 JournalArticle.class.getName(), article.getResourcePrimKey());
1031
1032
1033
1034 resourceLocalService.deleteResource(
1035 article.getCompanyId(), JournalArticle.class.getName(),
1036 ResourceConstants.SCOPE_INDIVIDUAL,
1037 article.getResourcePrimKey());
1038
1039
1040
1041 try {
1042 journalArticleResourceLocalService.deleteArticleResource(
1043 article.getGroupId(), article.getArticleId());
1044 }
1045 catch (NoSuchArticleResourceException nsare) {
1046 }
1047 }
1048
1049
1050
1051 journalArticlePersistence.remove(article);
1052 }
1053
1054
1070 public void deleteArticle(
1071 long groupId, String articleId, double version, String articleURL,
1072 ServiceContext serviceContext)
1073 throws PortalException, SystemException {
1074
1075 JournalArticle article = journalArticlePersistence.findByG_A_V(
1076 groupId, articleId, version);
1077
1078 deleteArticle(article, articleURL, serviceContext);
1079 }
1080
1081
1094 public void deleteArticle(
1095 long groupId, String articleId, ServiceContext serviceContext)
1096 throws PortalException, SystemException {
1097
1098 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
1099 groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
1100 new ArticleVersionComparator(true));
1101
1102 for (JournalArticle article : articles) {
1103 deleteArticle(article, null, serviceContext);
1104 }
1105 }
1106
1107
1114 public void deleteArticles(long groupId)
1115 throws PortalException, SystemException {
1116
1117 for (JournalArticle article :
1118 journalArticlePersistence.findByGroupId(groupId)) {
1119
1120 deleteArticle(article, null, null);
1121 }
1122 }
1123
1124
1133 public void deleteArticles(long groupId, long folderId)
1134 throws PortalException, SystemException {
1135
1136 deleteArticles(groupId, folderId, true);
1137 }
1138
1139
1150 public void deleteArticles(
1151 long groupId, long folderId, boolean includeTrashedEntries)
1152 throws PortalException, SystemException {
1153
1154 for (JournalArticle article :
1155 journalArticlePersistence.findByG_F(groupId, folderId)) {
1156
1157 if (includeTrashedEntries || !article.isInTrash()) {
1158 deleteArticle(article, null, null);
1159 }
1160 }
1161 }
1162
1163
1172 public void deleteLayoutArticleReferences(long groupId, String layoutUuid)
1173 throws SystemException {
1174
1175 List<JournalArticle> articles = journalArticlePersistence.findByG_L(
1176 groupId, layoutUuid);
1177
1178 for (JournalArticle article : articles) {
1179 article.setLayoutUuid(StringPool.BLANK);
1180
1181 journalArticlePersistence.update(article);
1182 }
1183 }
1184
1185
1208 public JournalArticle expireArticle(
1209 long userId, long groupId, String articleId, double version,
1210 String articleURL, ServiceContext serviceContext)
1211 throws PortalException, SystemException {
1212
1213 return updateStatus(
1214 userId, groupId, articleId, version,
1215 WorkflowConstants.STATUS_EXPIRED, articleURL,
1216 new HashMap<String, Serializable>(), serviceContext);
1217 }
1218
1219
1242 public void expireArticle(
1243 long userId, long groupId, String articleId, String articleURL,
1244 ServiceContext serviceContext)
1245 throws PortalException, SystemException {
1246
1247 if (PropsValues.JOURNAL_ARTICLE_EXPIRE_ALL_VERSIONS) {
1248 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
1249 groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
1250 new ArticleVersionComparator(true));
1251
1252 for (JournalArticle article : articles) {
1253 expireArticle(
1254 userId, groupId, article.getArticleId(),
1255 article.getVersion(), articleURL, serviceContext);
1256 }
1257 }
1258 else {
1259 JournalArticle article = getLatestArticle(
1260 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1261
1262 expireArticle(
1263 userId, groupId, article.getArticleId(), article.getVersion(),
1264 articleURL, serviceContext);
1265 }
1266 }
1267
1268
1276 public JournalArticle fetchArticle(String uuid, long groupId)
1277 throws SystemException {
1278
1279 return journalArticlePersistence.fetchByUUID_G(uuid, groupId);
1280 }
1281
1282
1291 public JournalArticle getArticle(long id)
1292 throws PortalException, SystemException {
1293
1294 return journalArticlePersistence.findByPrimaryKey(id);
1295 }
1296
1297
1309 public JournalArticle getArticle(long groupId, String articleId)
1310 throws PortalException, SystemException {
1311
1312
1313
1314
1315 try {
1316 return getLatestArticle(
1317 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1318 }
1319 catch (NoSuchArticleException nsae) {
1320 return getLatestArticle(
1321 groupId, articleId, WorkflowConstants.STATUS_ANY);
1322 }
1323 }
1324
1325
1337 public JournalArticle getArticle(
1338 long groupId, String articleId, double version)
1339 throws PortalException, SystemException {
1340
1341 return journalArticlePersistence.findByG_A_V(
1342 groupId, articleId, version);
1343 }
1344
1345
1363 public JournalArticle getArticle(
1364 long groupId, String className, long classPK)
1365 throws PortalException, SystemException {
1366
1367 long classNameId = PortalUtil.getClassNameId(className);
1368
1369 List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
1370 groupId, classNameId, classPK);
1371
1372 if (articles.isEmpty()) {
1373 throw new NoSuchArticleException(
1374 "No approved JournalArticle exists with the key {groupId=" +
1375 groupId + ", className=" + className + ", classPK=" +
1376 classPK + "}");
1377 }
1378
1379 return articles.get(0);
1380 }
1381
1382
1393 public JournalArticle getArticleByUrlTitle(long groupId, String urlTitle)
1394 throws PortalException, SystemException {
1395
1396
1397
1398
1399 try {
1400 return getLatestArticleByUrlTitle(
1401 groupId, urlTitle, WorkflowConstants.STATUS_APPROVED);
1402 }
1403 catch (NoSuchArticleException nsae) {
1404 return getLatestArticleByUrlTitle(
1405 groupId, urlTitle, WorkflowConstants.STATUS_PENDING);
1406 }
1407 }
1408
1409
1426 public String getArticleContent(
1427 JournalArticle article, String ddmTemplateKey, String viewMode,
1428 String languageId, ThemeDisplay themeDisplay)
1429 throws PortalException, SystemException {
1430
1431 JournalArticleDisplay articleDisplay = getArticleDisplay(
1432 article, ddmTemplateKey, viewMode, languageId, 1, null,
1433 themeDisplay);
1434
1435 if (articleDisplay == null) {
1436 return StringPool.BLANK;
1437 }
1438 else {
1439 return articleDisplay.getContent();
1440 }
1441 }
1442
1443
1462 public String getArticleContent(
1463 long groupId, String articleId, double version, String viewMode,
1464 String ddmTemplateKey, String languageId, ThemeDisplay themeDisplay)
1465 throws PortalException, SystemException {
1466
1467 JournalArticleDisplay articleDisplay = getArticleDisplay(
1468 groupId, articleId, version, ddmTemplateKey, viewMode, languageId,
1469 themeDisplay);
1470
1471 if (articleDisplay == null) {
1472 return StringPool.BLANK;
1473 }
1474 else {
1475 return articleDisplay.getContent();
1476 }
1477 }
1478
1479
1493 public String getArticleContent(
1494 long groupId, String articleId, double version, String viewMode,
1495 String languageId, ThemeDisplay themeDisplay)
1496 throws PortalException, SystemException {
1497
1498 return getArticleContent(
1499 groupId, articleId, version, viewMode, null, languageId,
1500 themeDisplay);
1501 }
1502
1503
1521 public String getArticleContent(
1522 long groupId, String articleId, String viewMode,
1523 String ddmTemplateKey, String languageId, ThemeDisplay themeDisplay)
1524 throws PortalException, SystemException {
1525
1526 JournalArticleDisplay articleDisplay = getArticleDisplay(
1527 groupId, articleId, ddmTemplateKey, viewMode, languageId,
1528 themeDisplay);
1529
1530 return articleDisplay.getContent();
1531 }
1532
1533
1546 public String getArticleContent(
1547 long groupId, String articleId, String viewMode, String languageId,
1548 ThemeDisplay themeDisplay)
1549 throws PortalException, SystemException {
1550
1551 return getArticleContent(
1552 groupId, articleId, viewMode, null, languageId, themeDisplay);
1553 }
1554
1555
1579 public JournalArticleDisplay getArticleDisplay(
1580 JournalArticle article, String ddmTemplateKey, String viewMode,
1581 String languageId, int page, String xmlRequest,
1582 ThemeDisplay themeDisplay)
1583 throws PortalException, SystemException {
1584
1585 String content = null;
1586
1587 if (page < 1) {
1588 page = 1;
1589 }
1590
1591 int numberOfPages = 1;
1592 boolean paginate = false;
1593 boolean pageFlow = false;
1594
1595 boolean cacheable = true;
1596
1597 if (Validator.isNull(xmlRequest)) {
1598 xmlRequest = "<request />";
1599 }
1600
1601 Map<String, String> tokens = JournalUtil.getTokens(
1602 article.getGroupId(), themeDisplay, xmlRequest);
1603
1604 tokens.put(
1605 "article_resource_pk",
1606 String.valueOf(article.getResourcePrimKey()));
1607
1608 String defaultDDMTemplateKey = article.getTemplateId();
1609
1610 if (article.isTemplateDriven()) {
1611 if (Validator.isNull(ddmTemplateKey)) {
1612 ddmTemplateKey = defaultDDMTemplateKey;
1613 }
1614
1615 tokens.put("structure_id", article.getStructureId());
1616 tokens.put("template_id", ddmTemplateKey);
1617 }
1618
1619 String xml = article.getContent();
1620
1621 try {
1622 Document document = null;
1623
1624 Element rootElement = null;
1625
1626 if (article.isTemplateDriven()) {
1627 document = SAXReaderUtil.read(xml);
1628
1629 rootElement = document.getRootElement();
1630
1631 Document requestDocument = SAXReaderUtil.read(xmlRequest);
1632
1633 List<Element> pages = rootElement.elements("page");
1634
1635 if (!pages.isEmpty()) {
1636 pageFlow = true;
1637
1638 String targetPage = requestDocument.valueOf(
1639 "/request/parameters/parameter[name='targetPage']/" +
1640 "value");
1641
1642 Element pageElement = null;
1643
1644 if (Validator.isNotNull(targetPage)) {
1645 targetPage = HtmlUtil.escapeXPathAttribute(targetPage);
1646
1647 XPath xPathSelector = SAXReaderUtil.createXPath(
1648 "/root/page[@id = " + targetPage + "]");
1649
1650 pageElement = (Element)xPathSelector.selectSingleNode(
1651 document);
1652 }
1653
1654 if (pageElement != null) {
1655 document = SAXReaderUtil.createDocument(pageElement);
1656
1657 rootElement = document.getRootElement();
1658
1659 numberOfPages = pages.size();
1660 }
1661 else {
1662 if (page > pages.size()) {
1663 page = 1;
1664 }
1665
1666 pageElement = pages.get(page - 1);
1667
1668 document = SAXReaderUtil.createDocument(pageElement);
1669
1670 rootElement = document.getRootElement();
1671
1672 numberOfPages = pages.size();
1673 paginate = true;
1674 }
1675 }
1676
1677 rootElement.add(requestDocument.getRootElement().createCopy());
1678
1679 JournalUtil.addAllReservedEls(
1680 rootElement, tokens, article, languageId, themeDisplay);
1681
1682 xml = DDMXMLUtil.formatXML(document);
1683 }
1684 }
1685 catch (DocumentException de) {
1686 throw new SystemException(de);
1687 }
1688
1689 try {
1690 if (_log.isDebugEnabled()) {
1691 _log.debug(
1692 "Transforming " + article.getArticleId() + " " +
1693 article.getVersion() + " " + languageId);
1694 }
1695
1696 String script = null;
1697 String langType = null;
1698
1699 if (article.isTemplateDriven()) {
1700
1701
1702
1703
1704
1705
1706
1707 DDMTemplate ddmTemplate = null;
1708
1709 try {
1710 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1711 article.getGroupId(),
1712 PortalUtil.getClassNameId(DDMStructure.class),
1713 ddmTemplateKey);
1714 }
1715 catch (NoSuchTemplateException nste1) {
1716 try {
1717 Group companyGroup = groupLocalService.getCompanyGroup(
1718 article.getCompanyId());
1719
1720 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1721 companyGroup.getGroupId(),
1722 PortalUtil.getClassNameId(DDMStructure.class),
1723 ddmTemplateKey);
1724
1725 tokens.put(
1726 "company_group_id",
1727 String.valueOf(companyGroup.getGroupId()));
1728 }
1729 catch (NoSuchTemplateException nste2) {
1730 if (!defaultDDMTemplateKey.equals(ddmTemplateKey)) {
1731 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
1732 article.getGroupId(),
1733 PortalUtil.getClassNameId(DDMStructure.class),
1734 defaultDDMTemplateKey);
1735 }
1736 else {
1737 throw nste1;
1738 }
1739 }
1740 }
1741
1742 script = ddmTemplate.getScript();
1743 langType = ddmTemplate.getLanguage();
1744 cacheable = ddmTemplate.isCacheable();
1745 }
1746
1747 content = JournalUtil.transform(
1748 themeDisplay, tokens, viewMode, languageId, xml, script,
1749 langType);
1750
1751 if (!pageFlow) {
1752 String[] pieces = StringUtil.split(
1753 content, PropsValues.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
1754
1755 if (pieces.length > 1) {
1756 if (page > pieces.length) {
1757 page = 1;
1758 }
1759
1760 content = pieces[page - 1];
1761 numberOfPages = pieces.length;
1762 paginate = true;
1763 }
1764 }
1765 }
1766 catch (Exception e) {
1767 throw new SystemException(e);
1768 }
1769
1770 return new JournalArticleDisplayImpl(
1771 article.getCompanyId(), article.getId(),
1772 article.getResourcePrimKey(), article.getGroupId(),
1773 article.getUserId(), article.getArticleId(), article.getVersion(),
1774 article.getTitle(languageId), article.getUrlTitle(),
1775 article.getDescription(languageId), article.getAvailableLocales(),
1776 content, article.getType(), article.getStructureId(),
1777 ddmTemplateKey, article.isSmallImage(), article.getSmallImageId(),
1778 article.getSmallImageURL(), numberOfPages, page, paginate,
1779 cacheable);
1780 }
1781
1782
1809 public JournalArticleDisplay getArticleDisplay(
1810 long groupId, String articleId, double version,
1811 String ddmTemplateKey, String viewMode, String languageId, int page,
1812 String xmlRequest, ThemeDisplay themeDisplay)
1813 throws PortalException, SystemException {
1814
1815 Date now = new Date();
1816
1817 JournalArticle article = journalArticlePersistence.findByG_A_V(
1818 groupId, articleId, version);
1819
1820 if (article.isExpired()) {
1821 Date expirationDate = article.getExpirationDate();
1822
1823 if ((expirationDate != null) && expirationDate.before(now)) {
1824 return null;
1825 }
1826 }
1827
1828 if (article.getDisplayDate().after(now)) {
1829 return null;
1830 }
1831
1832 return getArticleDisplay(
1833 article, ddmTemplateKey, viewMode, languageId, page, xmlRequest,
1834 themeDisplay);
1835 }
1836
1837
1861 public JournalArticleDisplay getArticleDisplay(
1862 long groupId, String articleId, double version,
1863 String ddmTemplateKey, String viewMode, String languageId,
1864 ThemeDisplay themeDisplay)
1865 throws PortalException, SystemException {
1866
1867 return getArticleDisplay(
1868 groupId, articleId, version, ddmTemplateKey, viewMode, languageId,
1869 1, null, themeDisplay);
1870 }
1871
1872
1894 public JournalArticleDisplay getArticleDisplay(
1895 long groupId, String articleId, String viewMode, String languageId,
1896 int page, String xmlRequest, ThemeDisplay themeDisplay)
1897 throws PortalException, SystemException {
1898
1899 return getArticleDisplay(
1900 groupId, articleId, null, viewMode, languageId, page, xmlRequest,
1901 themeDisplay);
1902 }
1903
1904
1931 public JournalArticleDisplay getArticleDisplay(
1932 long groupId, String articleId, String ddmTemplateKey,
1933 String viewMode, String languageId, int page, String xmlRequest,
1934 ThemeDisplay themeDisplay)
1935 throws PortalException, SystemException {
1936
1937 JournalArticle article = getDisplayArticle(groupId, articleId);
1938
1939 return getArticleDisplay(
1940 groupId, articleId, article.getVersion(), ddmTemplateKey, viewMode,
1941 languageId, page, xmlRequest, themeDisplay);
1942 }
1943
1944
1967 public JournalArticleDisplay getArticleDisplay(
1968 long groupId, String articleId, String ddmTemplateKey,
1969 String viewMode, String languageId, ThemeDisplay themeDisplay)
1970 throws PortalException, SystemException {
1971
1972 JournalArticle article = getDisplayArticle(groupId, articleId);
1973
1974 return getArticleDisplay(
1975 groupId, articleId, article.getVersion(), ddmTemplateKey, viewMode,
1976 languageId, themeDisplay);
1977 }
1978
1979
1997 public JournalArticleDisplay getArticleDisplay(
1998 long groupId, String articleId, String viewMode, String languageId,
1999 ThemeDisplay themeDisplay)
2000 throws PortalException, SystemException {
2001
2002 return getArticleDisplay(
2003 groupId, articleId, null, viewMode, languageId, themeDisplay);
2004 }
2005
2006
2012 public List<JournalArticle> getArticles() throws SystemException {
2013 return journalArticlePersistence.findAll();
2014 }
2015
2016
2023 public List<JournalArticle> getArticles(long groupId)
2024 throws SystemException {
2025
2026 return journalArticlePersistence.findByGroupId(groupId);
2027 }
2028
2029
2049 public List<JournalArticle> getArticles(long groupId, int start, int end)
2050 throws SystemException {
2051
2052 return journalArticlePersistence.findByGroupId(groupId, start, end);
2053 }
2054
2055
2078 public List<JournalArticle> getArticles(
2079 long groupId, int start, int end, OrderByComparator obc)
2080 throws SystemException {
2081
2082 return journalArticlePersistence.findByGroupId(
2083 groupId, start, end, obc);
2084 }
2085
2086
2094 public List<JournalArticle> getArticles(long groupId, long folderId)
2095 throws SystemException {
2096
2097 return journalArticlePersistence.findByG_F(groupId, folderId);
2098 }
2099
2100
2122 public List<JournalArticle> getArticles(
2123 long groupId, long folderId, int start, int end)
2124 throws SystemException {
2125
2126 return journalArticlePersistence.findByG_F(
2127 groupId, folderId, start, end);
2128 }
2129
2130
2155 public List<JournalArticle> getArticles(
2156 long groupId, long folderId, int start, int end,
2157 OrderByComparator orderByComparator)
2158 throws SystemException {
2159
2160 return journalArticlePersistence.findByG_F(
2161 groupId, folderId, start, end, orderByComparator);
2162 }
2163
2164
2172 public List<JournalArticle> getArticles(long groupId, String articleId)
2173 throws SystemException {
2174
2175 return journalArticlePersistence.findByG_A(groupId, articleId);
2176 }
2177
2178
2186 public List<JournalArticle> getArticlesBySmallImageId(long smallImageId)
2187 throws SystemException {
2188
2189 return journalArticlePersistence.findBySmallImageId(smallImageId);
2190 }
2191
2192
2199 public int getArticlesCount(long groupId) throws SystemException {
2200 return journalArticlePersistence.countByGroupId(groupId);
2201 }
2202
2203
2211 public int getArticlesCount(long groupId, long folderId)
2212 throws SystemException {
2213
2214 return journalArticlePersistence.countByG_F(groupId, folderId);
2215 }
2216
2217
2242 public List<JournalArticle> getCompanyArticles(
2243 long companyId, double version, int status, int start, int end)
2244 throws SystemException {
2245
2246 if (status == WorkflowConstants.STATUS_ANY) {
2247 return journalArticlePersistence.findByC_V(
2248 companyId, version, start, end, new ArticleIDComparator(true));
2249 }
2250 else {
2251 return journalArticlePersistence.findByC_V_ST(
2252 companyId, version, status, start, end,
2253 new ArticleIDComparator(true));
2254 }
2255 }
2256
2257
2281 public List<JournalArticle> getCompanyArticles(
2282 long companyId, int status, int start, int end)
2283 throws SystemException {
2284
2285 if (status == WorkflowConstants.STATUS_ANY) {
2286 return journalArticlePersistence.findByCompanyId(
2287 companyId, start, end, new ArticleIDComparator(true));
2288 }
2289 else {
2290 return journalArticlePersistence.findByC_ST(
2291 companyId, status, start, end, new ArticleIDComparator(true));
2292 }
2293 }
2294
2295
2320 public int getCompanyArticlesCount(
2321 long companyId, double version, int status, int start, int end)
2322 throws SystemException {
2323
2324 if (status == WorkflowConstants.STATUS_ANY) {
2325 return journalArticlePersistence.countByC_V(companyId, version);
2326 }
2327 else {
2328 return journalArticlePersistence.countByC_V_ST(
2329 companyId, version, status);
2330 }
2331 }
2332
2333
2344 public int getCompanyArticlesCount(long companyId, int status)
2345 throws SystemException {
2346
2347 if (status == WorkflowConstants.STATUS_ANY) {
2348 return journalArticlePersistence.countByCompanyId(companyId);
2349 }
2350 else {
2351 return journalArticlePersistence.countByC_ST(companyId, status);
2352 }
2353 }
2354
2355
2368 public JournalArticle getDisplayArticle(long groupId, String articleId)
2369 throws PortalException, SystemException {
2370
2371 List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
2372 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
2373
2374 if (articles.isEmpty()) {
2375 throw new NoSuchArticleException(
2376 "No approved JournalArticle exists with the key {groupId=" +
2377 groupId + ", " + "articleId=" + articleId + "}");
2378
2379 }
2380
2381 Date now = new Date();
2382
2383 for (int i = 0; i < articles.size(); i++) {
2384 JournalArticle article = articles.get(i);
2385
2386 Date expirationDate = article.getExpirationDate();
2387
2388 if (article.getDisplayDate().before(now) &&
2389 ((expirationDate == null) || expirationDate.after(now))) {
2390
2391 return article;
2392 }
2393 }
2394
2395 return articles.get(0);
2396 }
2397
2398
2411 public JournalArticle getDisplayArticleByUrlTitle(
2412 long groupId, String urlTitle)
2413 throws PortalException, SystemException {
2414
2415 List<JournalArticle> articles = null;
2416
2417 OrderByComparator orderByComparator = new ArticleVersionComparator();
2418
2419 articles = journalArticlePersistence.findByG_UT_ST(
2420 groupId, urlTitle, WorkflowConstants.STATUS_APPROVED,
2421 QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator);
2422
2423 if (articles.isEmpty()) {
2424 throw new NoSuchArticleException(
2425 "No JournalArticle exists with the key {groupId=" + groupId +
2426 ", urlTitle=" + urlTitle + "}");
2427 }
2428
2429 Date now = new Date();
2430
2431 for (JournalArticle article : articles) {
2432 Date expirationDate = article.getExpirationDate();
2433
2434 if (article.getDisplayDate().before(now) &&
2435 ((expirationDate == null) || expirationDate.after(now))) {
2436
2437 return article;
2438 }
2439 }
2440
2441 return articles.get(0);
2442 }
2443
2444
2455 public JournalArticle getLatestArticle(long resourcePrimKey)
2456 throws PortalException, SystemException {
2457
2458 return getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
2459 }
2460
2461
2476 public JournalArticle getLatestArticle(long resourcePrimKey, int status)
2477 throws PortalException, SystemException {
2478
2479 return getLatestArticle(resourcePrimKey, status, true);
2480 }
2481
2482
2502 public JournalArticle getLatestArticle(
2503 long resourcePrimKey, int status, boolean preferApproved)
2504 throws PortalException, SystemException {
2505
2506 List<JournalArticle> articles = null;
2507
2508 OrderByComparator orderByComparator = new ArticleVersionComparator();
2509
2510 if (status == WorkflowConstants.STATUS_ANY) {
2511 if (preferApproved) {
2512 articles = journalArticlePersistence.findByR_ST(
2513 resourcePrimKey, WorkflowConstants.STATUS_APPROVED, 0, 1,
2514 orderByComparator);
2515 }
2516
2517 if ((articles == null) || (articles.size() == 0)) {
2518 articles = journalArticlePersistence.findByResourcePrimKey(
2519 resourcePrimKey, 0, 1, orderByComparator);
2520 }
2521 }
2522 else {
2523 articles = journalArticlePersistence.findByR_ST(
2524 resourcePrimKey, status, 0, 1, orderByComparator);
2525 }
2526
2527 if (articles.isEmpty()) {
2528 throw new NoSuchArticleException(
2529 "No JournalArticle exists with the key {resourcePrimKey=" +
2530 resourcePrimKey + "}");
2531 }
2532
2533 return articles.get(0);
2534 }
2535
2536
2546 public JournalArticle getLatestArticle(long groupId, String articleId)
2547 throws PortalException, SystemException {
2548
2549 return getLatestArticle(
2550 groupId, articleId, WorkflowConstants.STATUS_ANY);
2551 }
2552
2553
2567 public JournalArticle getLatestArticle(
2568 long groupId, String articleId, int status)
2569 throws PortalException, SystemException {
2570
2571 List<JournalArticle> articles = null;
2572
2573 OrderByComparator orderByComparator = new ArticleVersionComparator();
2574
2575 if (status == WorkflowConstants.STATUS_ANY) {
2576 articles = journalArticlePersistence.findByG_A(
2577 groupId, articleId, 0, 1, orderByComparator);
2578 }
2579 else {
2580 articles = journalArticlePersistence.findByG_A_ST(
2581 groupId, articleId, status, 0, 1, orderByComparator);
2582 }
2583
2584 if (articles.isEmpty()) {
2585 throw new NoSuchArticleException(
2586 "No JournalArticle exists with the key {groupId=" + groupId +
2587 ", articleId=" + articleId + ", status=" + status + "}");
2588 }
2589
2590 return articles.get(0);
2591 }
2592
2593
2611 public JournalArticle getLatestArticle(
2612 long groupId, String className, long classPK)
2613 throws PortalException, SystemException {
2614
2615 long classNameId = PortalUtil.getClassNameId(className);
2616
2617 List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
2618 groupId, classNameId, classPK, 0, 1,
2619 new ArticleVersionComparator());
2620
2621 if (articles.isEmpty()) {
2622 throw new NoSuchArticleException(
2623 "No JournalArticle exists with the key {groupId=" + groupId +
2624 ", className=" + className + ", classPK =" + classPK + "}");
2625 }
2626
2627 return articles.get(0);
2628 }
2629
2630
2644 public JournalArticle getLatestArticleByUrlTitle(
2645 long groupId, String urlTitle, int status)
2646 throws PortalException, SystemException {
2647
2648 List<JournalArticle> articles = null;
2649
2650 OrderByComparator orderByComparator = new ArticleVersionComparator();
2651
2652 if (status == WorkflowConstants.STATUS_ANY) {
2653 articles = journalArticlePersistence.findByG_UT(
2654 groupId, urlTitle, 0, 1, orderByComparator);
2655 }
2656 else {
2657 articles = journalArticlePersistence.findByG_UT_ST(
2658 groupId, urlTitle, status, 0, 1, orderByComparator);
2659 }
2660
2661 if (articles.isEmpty()) {
2662 throw new NoSuchArticleException(
2663 "No JournalArticle exists with the key {groupId=" + groupId +
2664 ", urlTitle=" + urlTitle + ", status=" + status + "}");
2665 }
2666
2667 return articles.get(0);
2668 }
2669
2670
2681 public double getLatestVersion(long groupId, String articleId)
2682 throws PortalException, SystemException {
2683
2684 JournalArticle article = getLatestArticle(groupId, articleId);
2685
2686 return article.getVersion();
2687 }
2688
2689
2703 public double getLatestVersion(long groupId, String articleId, int status)
2704 throws PortalException, SystemException {
2705
2706 JournalArticle article = getLatestArticle(groupId, articleId, status);
2707
2708 return article.getVersion();
2709 }
2710
2711
2719 public int getNotInTrashArticlesCount(long groupId, long folderId)
2720 throws SystemException {
2721
2722 QueryDefinition queryDefinition = new QueryDefinition(
2723 WorkflowConstants.STATUS_ANY);
2724
2725 List<Long> folderIds = new ArrayList<Long>();
2726
2727 folderIds.add(folderId);
2728
2729 return journalArticleFinder.countByG_F(
2730 groupId, folderIds, queryDefinition);
2731 }
2732
2733
2743 public List<JournalArticle> getStructureArticles(
2744 long groupId, String ddmStructureKey)
2745 throws SystemException {
2746
2747 return journalArticlePersistence.findByG_S(groupId, ddmStructureKey);
2748 }
2749
2750
2775 public List<JournalArticle> getStructureArticles(
2776 long groupId, String ddmStructureKey, int start, int end,
2777 OrderByComparator obc)
2778 throws SystemException {
2779
2780 return journalArticlePersistence.findByG_S(
2781 groupId, ddmStructureKey, start, end, obc);
2782 }
2783
2784 public List<JournalArticle> getStructureArticles(String[] ddmStructureKeys)
2785 throws SystemException {
2786
2787 return journalArticlePersistence.findByStructureId(ddmStructureKeys);
2788 }
2789
2790
2800 public int getStructureArticlesCount(long groupId, String ddmStructureKey)
2801 throws SystemException {
2802
2803 return journalArticlePersistence.countByG_S(groupId, ddmStructureKey);
2804 }
2805
2806
2817 public List<JournalArticle> getTemplateArticles(
2818 long groupId, String ddmTemplateKey)
2819 throws SystemException {
2820
2821 return journalArticlePersistence.findByG_T(groupId, ddmTemplateKey);
2822 }
2823
2824
2851 public List<JournalArticle> getTemplateArticles(
2852 long groupId, String ddmTemplateKey, int start, int end,
2853 OrderByComparator obc)
2854 throws SystemException {
2855
2856 return journalArticlePersistence.findByG_T(
2857 groupId, ddmTemplateKey, start, end, obc);
2858 }
2859
2860
2872 public int getTemplateArticlesCount(long groupId, String ddmTemplateKey)
2873 throws SystemException {
2874
2875 return journalArticlePersistence.countByG_T(groupId, ddmTemplateKey);
2876 }
2877
2878
2887 public boolean hasArticle(long groupId, String articleId)
2888 throws SystemException {
2889
2890 try {
2891 getArticle(groupId, articleId);
2892
2893 return true;
2894 }
2895 catch (PortalException pe) {
2896 return false;
2897 }
2898 }
2899
2900
2913 public boolean isLatestVersion(
2914 long groupId, String articleId, double version)
2915 throws PortalException, SystemException {
2916
2917 if (getLatestVersion(groupId, articleId) == version) {
2918 return true;
2919 }
2920 else {
2921 return false;
2922 }
2923 }
2924
2925
2941 public boolean isLatestVersion(
2942 long groupId, String articleId, double version, int status)
2943 throws PortalException, SystemException {
2944
2945 if (getLatestVersion(groupId, articleId, status) == version) {
2946 return true;
2947 }
2948 else {
2949 return false;
2950 }
2951 }
2952
2953
2966 @Indexable(type = IndexableType.REINDEX)
2967 public JournalArticle moveArticle(
2968 long groupId, String articleId, long newFolderId)
2969 throws PortalException, SystemException {
2970
2971 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
2972 groupId, articleId);
2973
2974 for (JournalArticle article : articles) {
2975 article.setFolderId(newFolderId);
2976
2977 journalArticlePersistence.update(article);
2978 }
2979
2980 return getArticle(groupId, articleId);
2981 }
2982
2983
3006 public JournalArticle moveArticleFromTrash(
3007 long userId, long groupId, JournalArticle article, long newFolderId,
3008 ServiceContext serviceContext)
3009 throws PortalException, SystemException {
3010
3011 if (article.isInTrash()) {
3012 restoreArticleFromTrash(userId, article);
3013 }
3014 else {
3015 updateStatus(
3016 userId, article, article.getStatus(), null,
3017 new HashMap<String, Serializable>(), serviceContext);
3018 }
3019
3020 return journalArticleLocalService.moveArticle(
3021 groupId, article.getArticleId(), newFolderId);
3022 }
3023
3024
3037 public JournalArticle moveArticleToTrash(
3038 long userId, JournalArticle article)
3039 throws PortalException, SystemException {
3040
3041 List<JournalArticle> articleVersions =
3042 journalArticlePersistence.findByG_A(
3043 article.getGroupId(), article.getArticleId());
3044
3045 articleVersions = ListUtil.sort(
3046 articleVersions, new ArticleVersionComparator());
3047
3048 Map<String, Serializable> workflowContext =
3049 new HashMap<String, Serializable>();
3050
3051 workflowContext.put("articleVersions", (Serializable)articleVersions);
3052
3053 article = updateStatus(
3054 userId, article.getId(), WorkflowConstants.STATUS_IN_TRASH,
3055 workflowContext, new ServiceContext());
3056
3057
3058
3059 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3060 JournalArticle.class);
3061
3062 indexer.delete(article);
3063
3064 TrashEntry trashEntry = trashEntryLocalService.getEntry(
3065 JournalArticle.class.getName(), article.getResourcePrimKey());
3066
3067 String trashArticleId = TrashUtil.getTrashTitle(
3068 trashEntry.getEntryId());
3069
3070 if (!articleVersions.isEmpty()) {
3071 for (JournalArticle curArticleVersion : articleVersions) {
3072 curArticleVersion.setArticleId(trashArticleId);
3073
3074 journalArticlePersistence.update(curArticleVersion);
3075 }
3076 }
3077
3078 JournalArticleResource articleResource =
3079 journalArticleResourcePersistence.fetchByPrimaryKey(
3080 article.getResourcePrimKey());
3081
3082 articleResource.setArticleId(trashArticleId);
3083
3084 journalArticleResourcePersistence.update(articleResource);
3085
3086 article.setArticleId(trashArticleId);
3087
3088 reindex(article);
3089
3090 article = journalArticlePersistence.update(article);
3091
3092 socialActivityCounterLocalService.disableActivityCounters(
3093 JournalFolder.class.getName(), article.getFolderId());
3094
3095 socialActivityLocalService.addActivity(
3096 userId, article.getGroupId(), JournalArticle.class.getName(),
3097 article.getResourcePrimKey(),
3098 SocialActivityConstants.TYPE_MOVE_TO_TRASH, StringPool.BLANK, 0);
3099
3100 return article;
3101 }
3102
3103
3117 public JournalArticle moveArticleToTrash(
3118 long userId, long groupId, String articleId)
3119 throws PortalException, SystemException {
3120
3121 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
3122 groupId, articleId, 0, 1, new ArticleVersionComparator());
3123
3124 if (!articles.isEmpty()) {
3125 return moveArticleToTrash(userId, articles.get(0));
3126 }
3127
3128 return null;
3129 }
3130
3131
3144 public JournalArticle removeArticleLocale(
3145 long groupId, String articleId, double version, String languageId)
3146 throws PortalException, SystemException {
3147
3148 JournalArticle article = journalArticlePersistence.findByG_A_V(
3149 groupId, articleId, version);
3150
3151 String title = article.getTitle();
3152
3153 title = LocalizationUtil.removeLocalization(
3154 title, "static-content", languageId, true);
3155
3156 article.setTitle(title);
3157
3158 String description = article.getDescription();
3159
3160 description = LocalizationUtil.removeLocalization(
3161 description, "static-content", languageId, true);
3162
3163 article.setDescription(description);
3164
3165 String content = article.getContent();
3166
3167 if (article.isTemplateDriven()) {
3168 content = JournalUtil.removeArticleLocale(content, languageId);
3169 }
3170 else {
3171 content = LocalizationUtil.removeLocalization(
3172 content, "static-content", languageId, true);
3173 }
3174
3175 article.setContent(content);
3176
3177 journalArticlePersistence.update(article);
3178
3179 return article;
3180 }
3181
3182
3194 public void restoreArticleFromTrash(long userId, JournalArticle article)
3195 throws PortalException, SystemException {
3196
3197
3198
3199 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3200 JournalArticle.class);
3201
3202 indexer.delete(article);
3203
3204 String trashArticleId = TrashUtil.getOriginalTitle(
3205 article.getArticleId());
3206
3207 List<JournalArticle> articleVersions =
3208 journalArticlePersistence.findByG_A(
3209 article.getGroupId(), article.getArticleId());
3210
3211 if (!articleVersions.isEmpty()) {
3212 for (JournalArticle curArticleVersion : articleVersions) {
3213 curArticleVersion.setArticleId(trashArticleId);
3214
3215 journalArticlePersistence.update(curArticleVersion);
3216 }
3217 }
3218
3219 article.setArticleId(trashArticleId);
3220
3221 journalArticlePersistence.update(article);
3222
3223 JournalArticleResource articleResource =
3224 journalArticleResourcePersistence.fetchByPrimaryKey(
3225 article.getResourcePrimKey());
3226
3227 articleResource.setArticleId(trashArticleId);
3228
3229 journalArticleResourcePersistence.update(articleResource);
3230
3231 TrashEntry trashEntry = trashEntryLocalService.getEntry(
3232 JournalArticle.class.getName(), article.getResourcePrimKey());
3233
3234 Map<String, Serializable> workflowContext =
3235 new HashMap<String, Serializable>();
3236
3237 List<TrashVersion> trashVersions = trashEntryLocalService.getVersions(
3238 trashEntry.getEntryId());
3239
3240 workflowContext.put("trashVersions", (Serializable)trashVersions);
3241
3242 ServiceContext serviceContext = new ServiceContext();
3243
3244 serviceContext.setScopeGroupId(article.getGroupId());
3245
3246 updateStatus(
3247 userId, article, trashEntry.getStatus(), null, workflowContext,
3248 serviceContext);
3249
3250 socialActivityCounterLocalService.enableActivityCounters(
3251 JournalFolder.class.getName(), article.getFolderId());
3252
3253 socialActivityLocalService.addActivity(
3254 userId, article.getGroupId(), JournalArticle.class.getName(),
3255 article.getResourcePrimKey(),
3256 SocialActivityConstants.TYPE_RESTORE_FROM_TRASH, StringPool.BLANK,
3257 0);
3258 }
3259
3260
3322 public List<JournalArticle> search(
3323 long companyId, long groupId, List<Long> folderIds,
3324 long classNameId, String keywords, Double version, String type,
3325 String ddmStructureKey, String ddmTemplateKey, Date displayDateGT,
3326 Date displayDateLT, int status, Date reviewDate, int start, int end,
3327 OrderByComparator obc)
3328 throws SystemException {
3329
3330 return journalArticleFinder.findByKeywords(
3331 companyId, groupId, folderIds, classNameId, keywords, version, type,
3332 ddmStructureKey, ddmTemplateKey, displayDateGT, displayDateLT,
3333 status, reviewDate, start, end, obc);
3334 }
3335
3336
3405 public List<JournalArticle> search(
3406 long companyId, long groupId, List<Long> folderIds,
3407 long classNameId, String articleId, Double version, String title,
3408 String description, String content, String type,
3409 String ddmStructureKey, String ddmTemplateKey, Date displayDateGT,
3410 Date displayDateLT, int status, Date reviewDate,
3411 boolean andOperator, int start, int end, OrderByComparator obc)
3412 throws SystemException {
3413
3414 QueryDefinition queryDefinition = new QueryDefinition(
3415 status, start, end, obc);
3416
3417 return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
3418 companyId, groupId, folderIds, classNameId, articleId, version,
3419 title, description, content, type, ddmStructureKey, ddmTemplateKey,
3420 displayDateGT, displayDateLT, reviewDate, andOperator,
3421 queryDefinition);
3422 }
3423
3424
3490 public List<JournalArticle> search(
3491 long companyId, long groupId, List<Long> folderIds,
3492 long classNameId, String articleId, Double version, String title,
3493 String description, String content, String type,
3494 String[] ddmStructureKeys, String[] ddmTemplateKeys,
3495 Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
3496 boolean andOperator, int start, int end, OrderByComparator obc)
3497 throws SystemException {
3498
3499 QueryDefinition queryDefinition = new QueryDefinition(
3500 status, start, end, obc);
3501
3502 return journalArticleFinder.findByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
3503 companyId, groupId, folderIds, classNameId, articleId, version,
3504 title, description, content, type, ddmStructureKeys,
3505 ddmTemplateKeys, displayDateGT, displayDateLT, reviewDate,
3506 andOperator, queryDefinition);
3507 }
3508
3509
3556 public Hits search(
3557 long companyId, long groupId, List<Long> folderIds,
3558 long classNameId, String ddmStructureKey, String ddmTemplateKey,
3559 String keywords, LinkedHashMap<String, Object> params, int start,
3560 int end, Sort sort)
3561 throws SystemException {
3562
3563 String articleId = null;
3564 String title = null;
3565 String description = null;
3566 String content = null;
3567 boolean andOperator = false;
3568
3569 if (Validator.isNotNull(keywords)) {
3570 articleId = keywords;
3571 title = keywords;
3572 description = keywords;
3573 content = keywords;
3574 }
3575 else {
3576 andOperator = true;
3577 }
3578
3579 String status = String.valueOf(WorkflowConstants.STATUS_ANY);
3580
3581 if (params != null) {
3582 params.put("keywords", keywords);
3583 }
3584
3585 return search(
3586 companyId, groupId, folderIds, classNameId, articleId, title,
3587 description, content, null, status, ddmStructureKey, ddmTemplateKey,
3588 params, andOperator, start, end, sort);
3589 }
3590
3591
3652 public Hits search(
3653 long companyId, long groupId, List<Long> folderIds,
3654 long classNameId, String articleId, String title,
3655 String description, String content, String type, String status,
3656 String ddmStructureKey, String ddmTemplateKey,
3657 LinkedHashMap<String, Object> params, boolean andSearch, int start,
3658 int end, Sort sort)
3659 throws SystemException {
3660
3661 try {
3662 SearchContext searchContext = new SearchContext();
3663
3664 searchContext.setAndSearch(andSearch);
3665
3666 Map<String, Serializable> attributes =
3667 new HashMap<String, Serializable>();
3668
3669 attributes.put(Field.CLASS_NAME_ID, classNameId);
3670 attributes.put(Field.CONTENT, content);
3671 attributes.put(Field.DESCRIPTION, description);
3672 attributes.put(Field.STATUS, status);
3673 attributes.put(Field.TITLE, title);
3674 attributes.put(Field.TYPE, type);
3675 attributes.put("articleId", articleId);
3676 attributes.put("ddmStructureKey", ddmStructureKey);
3677 attributes.put("ddmTemplateKey", ddmTemplateKey);
3678 attributes.put("params", params);
3679
3680 searchContext.setAttributes(attributes);
3681
3682 searchContext.setCompanyId(companyId);
3683 searchContext.setEnd(end);
3684 searchContext.setFolderIds(folderIds);
3685 searchContext.setGroupIds(new long[] {groupId});
3686 searchContext.setIncludeDiscussions(
3687 GetterUtil.getBoolean(params.get("includeDiscussions")));
3688
3689 if (params != null) {
3690 String keywords = (String)params.remove("keywords");
3691
3692 if (Validator.isNotNull(keywords)) {
3693 searchContext.setKeywords(keywords);
3694 }
3695 }
3696
3697 QueryConfig queryConfig = new QueryConfig();
3698
3699 queryConfig.setHighlightEnabled(false);
3700 queryConfig.setScoreEnabled(false);
3701
3702 searchContext.setQueryConfig(queryConfig);
3703
3704 if (sort != null) {
3705 searchContext.setSorts(new Sort[] {sort});
3706 }
3707
3708 searchContext.setStart(start);
3709
3710 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
3711 JournalArticle.class);
3712
3713 return indexer.search(searchContext);
3714 }
3715 catch (Exception e) {
3716 throw new SystemException(e);
3717 }
3718 }
3719
3720
3764 public int searchCount(
3765 long companyId, long groupId, List<Long> folderIds,
3766 long classNameId, String keywords, Double version, String type,
3767 String ddmStructureKey, String ddmTemplateKey, Date displayDateGT,
3768 Date displayDateLT, int status, Date reviewDate)
3769 throws SystemException {
3770
3771 return journalArticleFinder.countByKeywords(
3772 companyId, groupId, folderIds, classNameId, keywords, version, type,
3773 ddmStructureKey, ddmTemplateKey, displayDateGT, displayDateLT,
3774 status, reviewDate);
3775 }
3776
3777
3827 public int searchCount(
3828 long companyId, long groupId, List<Long> folderIds,
3829 long classNameId, String articleId, Double version, String title,
3830 String description, String content, String type,
3831 String ddmStructureKey, String ddmTemplateKey, Date displayDateGT,
3832 Date displayDateLT, int status, Date reviewDate,
3833 boolean andOperator)
3834 throws SystemException {
3835
3836 return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
3837 companyId, groupId, folderIds, classNameId, articleId, version,
3838 title, description, content, type, ddmStructureKey, ddmTemplateKey,
3839 displayDateGT, displayDateLT, reviewDate, andOperator,
3840 new QueryDefinition(status));
3841 }
3842
3843
3893 public int searchCount(
3894 long companyId, long groupId, List<Long> folderIds,
3895 long classNameId, String articleId, Double version, String title,
3896 String description, String content, String type,
3897 String[] ddmStructureKeys, String[] ddmTemplateKeys,
3898 Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
3899 boolean andOperator)
3900 throws SystemException {
3901
3902 return journalArticleFinder.countByC_G_F_C_A_V_T_D_C_T_S_T_D_R(
3903 companyId, groupId, folderIds, classNameId, articleId, version,
3904 title, description, content, type, ddmStructureKeys,
3905 ddmTemplateKeys, displayDateGT, displayDateLT, reviewDate,
3906 andOperator, new QueryDefinition(status));
3907 }
3908
3909
3919 public void subscribe(long userId, long groupId)
3920 throws PortalException, SystemException {
3921
3922 subscriptionLocalService.addSubscription(
3923 userId, groupId, JournalArticle.class.getName(), groupId);
3924 }
3925
3926
3936 public void unsubscribe(long userId, long groupId)
3937 throws PortalException, SystemException {
3938
3939 subscriptionLocalService.deleteSubscription(
3940 userId, JournalArticle.class.getName(), groupId);
3941 }
3942
3943
3977 public JournalArticle updateArticle(
3978 long userId, long groupId, long folderId, String articleId,
3979 double version, Map<Locale, String> titleMap,
3980 Map<Locale, String> descriptionMap, String content,
3981 String layoutUuid, ServiceContext serviceContext)
3982 throws PortalException, SystemException {
3983
3984 User user = userPersistence.findByPrimaryKey(userId);
3985
3986 JournalArticle article = journalArticlePersistence.findByG_A_V(
3987 groupId, articleId, version);
3988
3989 Date displayDate = article.getDisplayDate();
3990
3991 int displayDateMonth = 0;
3992 int displayDateDay = 0;
3993 int displayDateYear = 0;
3994 int displayDateHour = 0;
3995 int displayDateMinute = 0;
3996
3997 if (displayDate != null) {
3998 Calendar displayCal = CalendarFactoryUtil.getCalendar(
3999 user.getTimeZone());
4000
4001 displayCal.setTime(displayDate);
4002
4003 displayDateMonth = displayCal.get(Calendar.MONTH);
4004 displayDateDay = displayCal.get(Calendar.DATE);
4005 displayDateYear = displayCal.get(Calendar.YEAR);
4006 displayDateHour = displayCal.get(Calendar.HOUR);
4007 displayDateMinute = displayCal.get(Calendar.MINUTE);
4008
4009 if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
4010 displayDateHour += 12;
4011 }
4012 }
4013
4014 Date expirationDate = article.getExpirationDate();
4015
4016 int expirationDateMonth = 0;
4017 int expirationDateDay = 0;
4018 int expirationDateYear = 0;
4019 int expirationDateHour = 0;
4020 int expirationDateMinute = 0;
4021 boolean neverExpire = true;
4022
4023 if (expirationDate != null) {
4024 Calendar expirationCal = CalendarFactoryUtil.getCalendar(
4025 user.getTimeZone());
4026
4027 expirationCal.setTime(expirationDate);
4028
4029 expirationDateMonth = expirationCal.get(Calendar.MONTH);
4030 expirationDateDay = expirationCal.get(Calendar.DATE);
4031 expirationDateYear = expirationCal.get(Calendar.YEAR);
4032 expirationDateHour = expirationCal.get(Calendar.HOUR);
4033 expirationDateMinute = expirationCal.get(Calendar.MINUTE);
4034 neverExpire = false;
4035
4036 if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
4037 expirationDateHour += 12;
4038 }
4039 }
4040
4041 Date reviewDate = article.getReviewDate();
4042
4043 int reviewDateMonth = 0;
4044 int reviewDateDay = 0;
4045 int reviewDateYear = 0;
4046 int reviewDateHour = 0;
4047 int reviewDateMinute = 0;
4048 boolean neverReview = true;
4049
4050 if (reviewDate != null) {
4051 Calendar reviewCal = CalendarFactoryUtil.getCalendar(
4052 user.getTimeZone());
4053
4054 reviewCal.setTime(reviewDate);
4055
4056 reviewDateMonth = reviewCal.get(Calendar.MONTH);
4057 reviewDateDay = reviewCal.get(Calendar.DATE);
4058 reviewDateYear = reviewCal.get(Calendar.YEAR);
4059 reviewDateHour = reviewCal.get(Calendar.HOUR);
4060 reviewDateMinute = reviewCal.get(Calendar.MINUTE);
4061 neverReview = false;
4062
4063 if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
4064 reviewDateHour += 12;
4065 }
4066 }
4067
4068 return updateArticle(
4069 userId, groupId, folderId, articleId, version, titleMap,
4070 descriptionMap, content, article.getType(),
4071 article.getStructureId(), article.getTemplateId(), layoutUuid,
4072 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
4073 displayDateMinute, expirationDateMonth, expirationDateDay,
4074 expirationDateYear, expirationDateHour, expirationDateMinute,
4075 neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
4076 reviewDateHour, reviewDateMinute, neverReview,
4077 article.getIndexable(), article.isSmallImage(),
4078 article.getSmallImageURL(), null, null, null, serviceContext);
4079 }
4080
4081
4168 public JournalArticle updateArticle(
4169 long userId, long groupId, long folderId, String articleId,
4170 double version, Map<Locale, String> titleMap,
4171 Map<Locale, String> descriptionMap, String content, String type,
4172 String ddmStructureKey, String ddmTemplateKey, String layoutUuid,
4173 int displayDateMonth, int displayDateDay, int displayDateYear,
4174 int displayDateHour, int displayDateMinute, int expirationDateMonth,
4175 int expirationDateDay, int expirationDateYear,
4176 int expirationDateHour, int expirationDateMinute,
4177 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
4178 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
4179 boolean neverReview, boolean indexable, boolean smallImage,
4180 String smallImageURL, File smallImageFile,
4181 Map<String, byte[]> images, String articleURL,
4182 ServiceContext serviceContext)
4183 throws PortalException, SystemException {
4184
4185
4186
4187 User user = userPersistence.findByPrimaryKey(userId);
4188 articleId = articleId.trim().toUpperCase();
4189
4190 byte[] smallImageBytes = null;
4191
4192 try {
4193 smallImageBytes = FileUtil.getBytes(smallImageFile);
4194 }
4195 catch (IOException ioe) {
4196 }
4197
4198 JournalArticle latestArticle = getLatestArticle(
4199 groupId, articleId, WorkflowConstants.STATUS_ANY);
4200
4201 JournalArticle article = latestArticle;
4202
4203 boolean imported = ExportImportThreadLocal.isImportInProcess();
4204
4205 double latestVersion = latestArticle.getVersion();
4206
4207 boolean addNewVersion = false;
4208
4209 if (imported) {
4210 if (latestVersion > version) {
4211 JournalArticle existingArticle =
4212 journalArticlePersistence.fetchByG_A_V(
4213 groupId, articleId, version);
4214
4215 if (existingArticle != null) {
4216 article = existingArticle;
4217 }
4218 else {
4219 addNewVersion = true;
4220 }
4221 }
4222 else if (latestVersion < version) {
4223 addNewVersion = true;
4224 }
4225 }
4226 else {
4227 if ((version > 0) && (version != latestVersion)) {
4228 throw new ArticleVersionException();
4229 }
4230
4231 serviceContext.validateModifiedDate(
4232 latestArticle, ArticleVersionException.class);
4233
4234 if (latestArticle.isApproved() || latestArticle.isExpired()) {
4235 addNewVersion = true;
4236
4237 version = MathUtil.format(latestVersion + 0.1, 1, 1);
4238 }
4239 }
4240
4241 Date displayDate = null;
4242 Date expirationDate = null;
4243 Date reviewDate = null;
4244
4245 if (article.getClassNameId() ==
4246 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
4247
4248 displayDate = PortalUtil.getDate(
4249 displayDateMonth, displayDateDay, displayDateYear,
4250 displayDateHour, displayDateMinute, user.getTimeZone(),
4251 ArticleDisplayDateException.class);
4252
4253 if (!neverExpire) {
4254 expirationDate = PortalUtil.getDate(
4255 expirationDateMonth, expirationDateDay, expirationDateYear,
4256 expirationDateHour, expirationDateMinute,
4257 user.getTimeZone(), ArticleExpirationDateException.class);
4258 }
4259
4260 if (!neverReview) {
4261 reviewDate = PortalUtil.getDate(
4262 reviewDateMonth, reviewDateDay, reviewDateYear,
4263 reviewDateHour, reviewDateMinute, user.getTimeZone(),
4264 ArticleReviewDateException.class);
4265 }
4266 }
4267
4268 Date now = new Date();
4269
4270 boolean expired = false;
4271
4272 if ((expirationDate != null) && expirationDate.before(now)) {
4273 expired = true;
4274 }
4275
4276 validate(
4277 user.getCompanyId(), groupId, latestArticle.getClassNameId(),
4278 titleMap, content, type, ddmStructureKey, ddmTemplateKey,
4279 expirationDate, smallImage, smallImageURL, smallImageFile,
4280 smallImageBytes);
4281
4282 if (addNewVersion) {
4283 long id = counterLocalService.increment();
4284
4285 article = journalArticlePersistence.create(id);
4286
4287 article.setResourcePrimKey(latestArticle.getResourcePrimKey());
4288 article.setGroupId(latestArticle.getGroupId());
4289 article.setCompanyId(latestArticle.getCompanyId());
4290 article.setUserId(user.getUserId());
4291 article.setUserName(user.getFullName());
4292 article.setCreateDate(serviceContext.getModifiedDate(now));
4293 article.setClassNameId(latestArticle.getClassNameId());
4294 article.setClassPK(latestArticle.getClassPK());
4295 article.setArticleId(articleId);
4296 article.setVersion(version);
4297 article.setSmallImageId(latestArticle.getSmallImageId());
4298 }
4299
4300 Locale locale = LocaleUtil.getDefault();
4301
4302 String defaultLanguageId = ParamUtil.getString(
4303 serviceContext, "defaultLanguageId");
4304
4305 if (Validator.isNull(defaultLanguageId)) {
4306 defaultLanguageId = LocalizationUtil.getDefaultLocale(content);
4307 }
4308
4309 if (Validator.isNotNull(defaultLanguageId)) {
4310 locale = LocaleUtil.fromLanguageId(defaultLanguageId);
4311 }
4312
4313 String title = titleMap.get(locale);
4314
4315 content = format(
4316 user, groupId, articleId, article.getVersion(), addNewVersion,
4317 content, ddmStructureKey, images);
4318
4319 article.setModifiedDate(serviceContext.getModifiedDate(now));
4320 article.setFolderId(folderId);
4321 article.setTitleMap(titleMap, locale);
4322 article.setUrlTitle(
4323 getUniqueUrlTitle(
4324 article.getId(), article.getArticleId(), title,
4325 latestArticle.getUrlTitle(), serviceContext));
4326 article.setDescriptionMap(descriptionMap, locale);
4327 article.setContent(content);
4328 article.setType(type);
4329 article.setStructureId(ddmStructureKey);
4330 article.setTemplateId(ddmTemplateKey);
4331 article.setLayoutUuid(layoutUuid);
4332 article.setDisplayDate(displayDate);
4333 article.setExpirationDate(expirationDate);
4334 article.setReviewDate(reviewDate);
4335 article.setIndexable(indexable);
4336 article.setSmallImage(smallImage);
4337
4338 if (smallImage) {
4339 if ((smallImageFile != null) && (smallImageBytes != null)) {
4340 article.setSmallImageId(counterLocalService.increment());
4341 }
4342 }
4343 else {
4344 article.setSmallImageId(0);
4345 }
4346
4347 article.setSmallImageURL(smallImageURL);
4348
4349 if (latestArticle.isPending()) {
4350 article.setStatus(latestArticle.getStatus());
4351 }
4352 else if (!expired) {
4353 article.setStatus(WorkflowConstants.STATUS_DRAFT);
4354 }
4355 else {
4356 article.setStatus(WorkflowConstants.STATUS_EXPIRED);
4357 }
4358
4359 article.setExpandoBridgeAttributes(serviceContext);
4360
4361 journalArticlePersistence.update(article);
4362
4363
4364
4365 updateAsset(
4366 userId, article, serviceContext.getAssetCategoryIds(),
4367 serviceContext.getAssetTagNames(),
4368 serviceContext.getAssetLinkEntryIds());
4369
4370
4371
4372 if (PortalUtil.getClassNameId(DDMStructure.class) ==
4373 article.getClassNameId()) {
4374
4375 updateDDMStructureXSD(
4376 article.getClassPK(), content, serviceContext);
4377 }
4378
4379
4380
4381 saveImages(
4382 smallImage, article.getSmallImageId(), smallImageFile,
4383 smallImageBytes);
4384
4385
4386
4387 PortletPreferences preferences =
4388 ServiceContextUtil.getPortletPreferences(serviceContext);
4389
4390
4391
4392 if (expired && imported) {
4393 updateStatus(
4394 userId, article, article.getStatus(), articleURL,
4395 new HashMap<String, Serializable>(), serviceContext);
4396 }
4397
4398 if (serviceContext.getWorkflowAction() ==
4399 WorkflowConstants.ACTION_PUBLISH) {
4400
4401 sendEmail(
4402 article, articleURL, preferences, "requested", serviceContext);
4403
4404 WorkflowHandlerRegistryUtil.startWorkflowInstance(
4405 user.getCompanyId(), groupId, userId,
4406 JournalArticle.class.getName(), article.getId(), article,
4407 serviceContext);
4408 }
4409 else if (article.getVersion() ==
4410 JournalArticleConstants.VERSION_DEFAULT) {
4411
4412
4413
4414 reindex(article);
4415 }
4416
4417 return article;
4418 }
4419
4420
4449 public JournalArticle updateArticle(
4450 long userId, long groupId, long folderId, String articleId,
4451 double version, String content, ServiceContext serviceContext)
4452 throws PortalException, SystemException {
4453
4454 JournalArticle article = journalArticlePersistence.findByG_A_V(
4455 groupId, articleId, version);
4456
4457 return updateArticle(
4458 userId, groupId, folderId, articleId, version,
4459 article.getTitleMap(), article.getDescriptionMap(), content,
4460 article.getLayoutUuid(), serviceContext);
4461 }
4462
4463
4468 public JournalArticle updateArticleTranslation(
4469 long groupId, String articleId, double version, Locale locale,
4470 String title, String description, String content,
4471 Map<String, byte[]> images)
4472 throws PortalException, SystemException {
4473
4474 return updateArticleTranslation(
4475 groupId, articleId, version, locale, title, description, content,
4476 images, null);
4477 }
4478
4479
4501 public JournalArticle updateArticleTranslation(
4502 long groupId, String articleId, double version, Locale locale,
4503 String title, String description, String content,
4504 Map<String, byte[]> images, ServiceContext serviceContext)
4505 throws PortalException, SystemException {
4506
4507 validateContent(content);
4508
4509 JournalArticle oldArticle = getLatestArticle(
4510 groupId, articleId, WorkflowConstants.STATUS_ANY);
4511
4512 double oldVersion = oldArticle.getVersion();
4513
4514 if ((version > 0) && (version != oldVersion)) {
4515 throw new ArticleVersionException();
4516 }
4517
4518 boolean incrementVersion = false;
4519
4520 if (oldArticle.isApproved() || oldArticle.isExpired()) {
4521 incrementVersion = true;
4522 }
4523
4524 if (serviceContext != null) {
4525 serviceContext.validateModifiedDate(
4526 oldArticle, ArticleVersionException.class);
4527 }
4528
4529 JournalArticle article = null;
4530
4531 User user = userPersistence.findByPrimaryKey(oldArticle.getUserId());
4532
4533 if (incrementVersion) {
4534 double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
4535
4536 long id = counterLocalService.increment();
4537
4538 article = journalArticlePersistence.create(id);
4539
4540 article.setResourcePrimKey(oldArticle.getResourcePrimKey());
4541 article.setGroupId(oldArticle.getGroupId());
4542 article.setCompanyId(oldArticle.getCompanyId());
4543 article.setUserId(oldArticle.getUserId());
4544 article.setUserName(user.getFullName());
4545 article.setCreateDate(new Date());
4546 article.setModifiedDate(new Date());
4547 article.setClassNameId(oldArticle.getClassNameId());
4548 article.setClassPK(oldArticle.getClassPK());
4549 article.setArticleId(articleId);
4550 article.setVersion(newVersion);
4551 article.setTitleMap(oldArticle.getTitleMap());
4552 article.setUrlTitle(
4553 getUniqueUrlTitle(
4554 id, articleId, title, oldArticle.getUrlTitle(),
4555 serviceContext));
4556 article.setDescriptionMap(oldArticle.getDescriptionMap());
4557 article.setType(oldArticle.getType());
4558 article.setStructureId(oldArticle.getStructureId());
4559 article.setTemplateId(oldArticle.getTemplateId());
4560 article.setLayoutUuid(oldArticle.getLayoutUuid());
4561 article.setDisplayDate(oldArticle.getDisplayDate());
4562 article.setExpirationDate(oldArticle.getExpirationDate());
4563 article.setReviewDate(oldArticle.getReviewDate());
4564 article.setIndexable(oldArticle.getIndexable());
4565 article.setSmallImage(oldArticle.getSmallImage());
4566 article.setSmallImageId(oldArticle.getSmallImageId());
4567
4568 if (article.getSmallImageId() == 0) {
4569 article.setSmallImageId(counterLocalService.increment());
4570 }
4571
4572 article.setSmallImageURL(oldArticle.getSmallImageURL());
4573
4574 article.setStatus(WorkflowConstants.STATUS_DRAFT);
4575 article.setStatusDate(new Date());
4576 }
4577 else {
4578 article = oldArticle;
4579 }
4580
4581 Map<Locale, String> titleMap = article.getTitleMap();
4582
4583 titleMap.put(locale, title);
4584
4585 article.setTitleMap(titleMap);
4586
4587 Map<Locale, String> descriptionMap = article.getDescriptionMap();
4588
4589 descriptionMap.put(locale, description);
4590
4591 article.setDescriptionMap(descriptionMap);
4592
4593 content = format(
4594 user, groupId, articleId, article.getVersion(),
4595 !oldArticle.isDraft(), content, oldArticle.getStructureId(),
4596 images);
4597
4598 article.setContent(content);
4599
4600 journalArticlePersistence.update(article);
4601
4602 return article;
4603 }
4604
4605
4618 public void updateAsset(
4619 long userId, JournalArticle article, long[] assetCategoryIds,
4620 String[] assetTagNames, long[] assetLinkEntryIds)
4621 throws PortalException, SystemException {
4622
4623 boolean visible = article.isApproved();
4624
4625 if (article.getClassNameId() !=
4626 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
4627
4628 visible = false;
4629 }
4630
4631 boolean addDraftAssetEntry = false;
4632
4633 if (!article.isApproved() &&
4634 (article.getVersion() != JournalArticleConstants.VERSION_DEFAULT)) {
4635
4636 int approvedArticlesCount = journalArticlePersistence.countByG_A_ST(
4637 article.getGroupId(), article.getArticleId(),
4638 JournalArticleConstants.ASSET_ENTRY_CREATION_STATUSES);
4639
4640 if (approvedArticlesCount > 0) {
4641 addDraftAssetEntry = true;
4642 }
4643 }
4644
4645 AssetEntry assetEntry = null;
4646
4647 if (addDraftAssetEntry) {
4648 assetEntry = assetEntryLocalService.updateEntry(
4649 userId, article.getGroupId(), article.getCreateDate(),
4650 article.getModifiedDate(), JournalArticle.class.getName(),
4651 article.getPrimaryKey(), article.getUuid(),
4652 getClassTypeId(article), assetCategoryIds, assetTagNames, false,
4653 null, null, null, ContentTypes.TEXT_HTML, article.getTitle(),
4654 article.getDescription(), article.getDescription(), null,
4655 article.getLayoutUuid(), 0, 0, null, false);
4656 }
4657 else {
4658 JournalArticleResource journalArticleResource =
4659 journalArticleResourceLocalService.getArticleResource(
4660 article.getResourcePrimKey());
4661
4662 assetEntry = assetEntryLocalService.updateEntry(
4663 userId, article.getGroupId(), article.getCreateDate(),
4664 article.getModifiedDate(), JournalArticle.class.getName(),
4665 journalArticleResource.getResourcePrimKey(),
4666 journalArticleResource.getUuid(), getClassTypeId(article),
4667 assetCategoryIds, assetTagNames, visible, null, null, null,
4668 ContentTypes.TEXT_HTML, article.getTitle(),
4669 article.getDescription(), article.getDescription(), null,
4670 article.getLayoutUuid(), 0, 0, null, false);
4671 }
4672
4673 assetLinkLocalService.updateLinks(
4674 userId, assetEntry.getEntryId(), assetLinkEntryIds,
4675 AssetLinkConstants.TYPE_RELATED);
4676 }
4677
4678
4693 public JournalArticle updateContent(
4694 long groupId, String articleId, double version, String content)
4695 throws PortalException, SystemException {
4696
4697 JournalArticle article = journalArticlePersistence.findByG_A_V(
4698 groupId, articleId, version);
4699
4700 article.setContent(content);
4701
4702 journalArticlePersistence.update(article);
4703
4704 return article;
4705 }
4706
4707
4730 public JournalArticle updateStatus(
4731 long userId, JournalArticle article, int status, String articleURL,
4732 Map<String, Serializable> workflowContext,
4733 ServiceContext serviceContext)
4734 throws PortalException, SystemException {
4735
4736
4737
4738 User user = userPersistence.findByPrimaryKey(userId);
4739 Date now = new Date();
4740
4741 int oldStatus = article.getStatus();
4742
4743 int oldArticleVersionStatus = WorkflowConstants.STATUS_ANY;
4744
4745 List<ObjectValuePair<Long, Integer>> articleVersionStatusOVPs =
4746 new ArrayList<ObjectValuePair<Long, Integer>>();
4747
4748 List<JournalArticle> articleVersions =
4749 (List<JournalArticle>)workflowContext.get("articleVersions");
4750
4751 if ((articleVersions != null) && !articleVersions.isEmpty()) {
4752 JournalArticle oldArticleVersion = articleVersions.get(0);
4753
4754 oldArticleVersionStatus = oldArticleVersion.getStatus();
4755
4756 articleVersionStatusOVPs = getArticleVersionStatuses(
4757 articleVersions);
4758 }
4759
4760 article.setModifiedDate(serviceContext.getModifiedDate(now));
4761
4762 boolean neverExpire = false;
4763
4764 if (status == WorkflowConstants.STATUS_APPROVED) {
4765 Date expirationDate = article.getExpirationDate();
4766
4767 if ((expirationDate != null) && expirationDate.before(now)) {
4768 neverExpire = true;
4769
4770 article.setExpirationDate(null);
4771 }
4772 }
4773
4774 if (status == WorkflowConstants.STATUS_EXPIRED) {
4775 article.setExpirationDate(now);
4776 }
4777
4778 article.setStatus(status);
4779 article.setStatusByUserId(user.getUserId());
4780 article.setStatusByUserName(user.getFullName());
4781 article.setStatusDate(serviceContext.getModifiedDate(now));
4782
4783 journalArticlePersistence.update(article);
4784
4785 if (hasModifiedLatestApprovedVersion(
4786 article.getGroupId(), article.getArticleId(),
4787 article.getVersion())) {
4788
4789 if (status == WorkflowConstants.STATUS_APPROVED) {
4790 updateUrlTitles(
4791 article.getGroupId(), article.getArticleId(),
4792 article.getUrlTitle());
4793
4794
4795
4796 if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
4797 (article.getVersion() !=
4798 JournalArticleConstants.VERSION_DEFAULT)) {
4799
4800 AssetEntry draftAssetEntry = null;
4801
4802 try {
4803 draftAssetEntry = assetEntryLocalService.getEntry(
4804 JournalArticle.class.getName(),
4805 article.getPrimaryKey());
4806
4807 long[] assetCategoryIds =
4808 draftAssetEntry.getCategoryIds();
4809 String[] assetTagNames = draftAssetEntry.getTagNames();
4810
4811 List<AssetLink> assetLinks =
4812 assetLinkLocalService.getDirectLinks(
4813 draftAssetEntry.getEntryId(),
4814 AssetLinkConstants.TYPE_RELATED);
4815
4816 long[] assetLinkEntryIds = StringUtil.split(
4817 ListUtil.toString(
4818 assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
4819
4820 AssetEntry assetEntry =
4821 assetEntryLocalService.updateEntry(
4822 userId, article.getGroupId(),
4823 article.getCreateDate(),
4824 article.getModifiedDate(),
4825 JournalArticle.class.getName(),
4826 article.getResourcePrimKey(), article.getUuid(),
4827 getClassTypeId(article), assetCategoryIds,
4828 assetTagNames, false, null, null, null,
4829 ContentTypes.TEXT_HTML, article.getTitle(),
4830 article.getDescription(),
4831 article.getDescription(), null,
4832 article.getLayoutUuid(), 0, 0, null, false);
4833
4834 assetLinkLocalService.updateLinks(
4835 userId, assetEntry.getEntryId(), assetLinkEntryIds,
4836 AssetLinkConstants.TYPE_RELATED);
4837
4838 assetEntryLocalService.deleteEntry(
4839 JournalArticle.class.getName(),
4840 article.getPrimaryKey());
4841 }
4842 catch (NoSuchEntryException nsee) {
4843 }
4844 }
4845
4846 if (article.getClassNameId() ==
4847 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
4848
4849
4850
4851
4852 Date[] dateInterval = getDateInterval(
4853 article.getGroupId(), article.getArticleId(),
4854 article.getDisplayDate(), article.getExpirationDate());
4855
4856 Date displayDate = dateInterval[0];
4857 Date expirationDate = dateInterval[1];
4858
4859 if (neverExpire) {
4860 expirationDate = null;
4861 }
4862
4863 assetEntryLocalService.updateEntry(
4864 JournalArticle.class.getName(),
4865 article.getResourcePrimKey(), displayDate,
4866 expirationDate, true);
4867 }
4868
4869
4870
4871 if (serviceContext.isCommandUpdate()) {
4872 socialActivityLocalService.addActivity(
4873 user.getUserId(), article.getGroupId(),
4874 JournalArticle.class.getName(),
4875 article.getResourcePrimKey(),
4876 JournalActivityKeys.UPDATE_ARTICLE,
4877 getExtraDataJSON(article, serviceContext), 0);
4878 }
4879 else {
4880 socialActivityLocalService.addUniqueActivity(
4881 user.getUserId(), article.getGroupId(),
4882 JournalArticle.class.getName(),
4883 article.getResourcePrimKey(),
4884 JournalActivityKeys.ADD_ARTICLE,
4885 getExtraDataJSON(article, serviceContext), 0);
4886 }
4887
4888
4889
4890 reindex(article);
4891 }
4892 else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
4893 updatePreviousApprovedArticle(article);
4894 }
4895 }
4896
4897 if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
4898
4899
4900
4901 List<TrashVersion> trashVersions =
4902 (List<TrashVersion>)workflowContext.get("trashVersions");
4903
4904 for (TrashVersion trashVersion : trashVersions) {
4905 JournalArticle trashArticleVersion =
4906 journalArticlePersistence.findByPrimaryKey(
4907 trashVersion.getClassPK());
4908
4909 trashArticleVersion.setStatus(trashVersion.getStatus());
4910
4911 journalArticlePersistence.update(trashArticleVersion);
4912 }
4913
4914 trashEntryLocalService.deleteEntry(
4915 JournalArticle.class.getName(), article.getResourcePrimKey());
4916
4917
4918
4919 if (status == WorkflowConstants.STATUS_APPROVED) {
4920 reindex(article);
4921 }
4922 else {
4923 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
4924 JournalArticle.class);
4925
4926 indexer.delete(article);
4927 }
4928
4929 }
4930 else if (status == WorkflowConstants.STATUS_IN_TRASH) {
4931 assetEntryLocalService.updateVisible(
4932 JournalArticle.class.getName(), article.getResourcePrimKey(),
4933 false);
4934
4935
4936
4937 for (JournalArticle curArticleVersion : articleVersions) {
4938 curArticleVersion.setStatus(WorkflowConstants.STATUS_IN_TRASH);
4939
4940 journalArticlePersistence.update(curArticleVersion);
4941 }
4942
4943 UnicodeProperties typeSettingsProperties = new UnicodeProperties();
4944
4945 typeSettingsProperties.put("title", article.getArticleId());
4946
4947 trashEntryLocalService.addTrashEntry(
4948 userId, article.getGroupId(), JournalArticle.class.getName(),
4949 article.getResourcePrimKey(), oldArticleVersionStatus,
4950 articleVersionStatusOVPs, typeSettingsProperties);
4951
4952
4953
4954 reindex(article);
4955 }
4956
4957 if ((article.getClassNameId() ==
4958 JournalArticleConstants.CLASSNAME_ID_DEFAULT) &&
4959 (oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
4960 (status != WorkflowConstants.STATUS_IN_TRASH)) {
4961
4962
4963
4964 if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
4965 ((status == WorkflowConstants.STATUS_APPROVED) ||
4966 (status == WorkflowConstants.STATUS_DENIED))) {
4967
4968 String msg = "granted";
4969
4970 if (status == WorkflowConstants.STATUS_DENIED) {
4971 msg = "denied";
4972 }
4973
4974 try {
4975 PortletPreferences preferences =
4976 ServiceContextUtil.getPortletPreferences(
4977 serviceContext);
4978
4979 sendEmail(
4980 article, articleURL, preferences, msg, serviceContext);
4981 }
4982 catch (Exception e) {
4983 _log.error(
4984 "Unable to send email to notify the change of status " +
4985 " to " + msg + " for article " + article.getId() +
4986 ": " + e.getMessage());
4987 }
4988 }
4989
4990
4991
4992 notifySubscribers(article, serviceContext);
4993 }
4994
4995 return article;
4996 }
4997
4998
5019 public JournalArticle updateStatus(
5020 long userId, long classPK, int status,
5021 Map<String, Serializable> workflowContext,
5022 ServiceContext serviceContext)
5023 throws PortalException, SystemException {
5024
5025 JournalArticle article = getArticle(classPK);
5026
5027 return updateStatus(
5028 userId, article, status, null, workflowContext, serviceContext);
5029 }
5030
5031
5053 public JournalArticle updateStatus(
5054 long userId, long groupId, String articleId, double version,
5055 int status, String articleURL,
5056 Map<String, Serializable> workflowContext,
5057 ServiceContext serviceContext)
5058 throws PortalException, SystemException {
5059
5060 JournalArticle article = journalArticlePersistence.findByG_A_V(
5061 groupId, articleId, version);
5062
5063 return updateStatus(
5064 userId, article, status, articleURL, workflowContext,
5065 serviceContext);
5066 }
5067
5068
5083 public void updateTemplateId(
5084 long groupId, long classNameId, String oldDDMTemplateKey,
5085 String newDDMTemplateKey)
5086 throws SystemException {
5087
5088 List<JournalArticle> articles = journalArticlePersistence.findByG_C_T(
5089 groupId, classNameId, oldDDMTemplateKey);
5090
5091 for (JournalArticle article : articles) {
5092 article.setTemplateId(newDDMTemplateKey);
5093
5094 journalArticlePersistence.update(article);
5095 }
5096 }
5097
5098 protected void checkStructure(Document contentDoc, Element root)
5099 throws PortalException {
5100
5101 for (Element el : root.elements()) {
5102 checkStructureField(el, contentDoc);
5103
5104 checkStructure(contentDoc, el);
5105 }
5106 }
5107
5108 protected void checkStructure(JournalArticle article)
5109 throws PortalException, SystemException {
5110
5111 Group companyGroup = groupLocalService.getCompanyGroup(
5112 article.getCompanyId());
5113
5114 DDMStructure structure = null;
5115
5116 try {
5117 structure = ddmStructurePersistence.findByG_C_S(
5118 article.getGroupId(),
5119 PortalUtil.getClassNameId(JournalArticle.class),
5120 article.getStructureId());
5121 }
5122 catch (NoSuchStructureException nsse) {
5123 structure = ddmStructurePersistence.findByG_C_S(
5124 companyGroup.getGroupId(),
5125 PortalUtil.getClassNameId(JournalArticle.class),
5126 article.getStructureId());
5127 }
5128
5129 String content = GetterUtil.getString(article.getContent());
5130
5131 try {
5132 Document contentDocument = SAXReaderUtil.read(content);
5133 Document xsdDocument = SAXReaderUtil.read(structure.getXsd());
5134
5135 checkStructure(contentDocument, xsdDocument.getRootElement());
5136 }
5137 catch (DocumentException de) {
5138 throw new SystemException(de);
5139 }
5140 catch (StructureXsdException sxsde) {
5141 long groupId = article.getGroupId();
5142 String articleId = article.getArticleId();
5143 double version = article.getVersion();
5144
5145 if (_log.isWarnEnabled()) {
5146 _log.warn(
5147 "Article {groupId=" + groupId + ", articleId=" +
5148 articleId + ", version=" + version +
5149 "} has content that does not match its " +
5150 "structure: " + sxsde.getMessage());
5151 }
5152 }
5153 }
5154
5155 protected void checkStructureField(Element el, Document contentDoc)
5156 throws PortalException {
5157
5158 StringBuilder elPath = new StringBuilder();
5159
5160 elPath.append(el.attributeValue("name"));
5161
5162 Element elParent = el.getParent();
5163
5164 for (;;) {
5165 if ((elParent == null) || elParent.getName().equals("root")) {
5166 break;
5167 }
5168
5169 elPath.insert(
5170 0, elParent.attributeValue("name") + StringPool.COMMA);
5171
5172 elParent = elParent.getParent();
5173 }
5174
5175 String[] elPathNames = StringUtil.split(elPath.toString());
5176
5177 Element contentEl = contentDoc.getRootElement();
5178
5179 for (String _elPathName : elPathNames) {
5180 boolean foundEl = false;
5181
5182 for (Element tempEl : contentEl.elements()) {
5183 if (_elPathName.equals(
5184 tempEl.attributeValue("name", StringPool.BLANK))) {
5185
5186 contentEl = tempEl;
5187 foundEl = true;
5188
5189 break;
5190 }
5191 }
5192
5193 if (!foundEl) {
5194 String elType = contentEl.attributeValue(
5195 "type", StringPool.BLANK);
5196
5197 if (!elType.equals("list") && !elType.equals("multi-list")) {
5198 throw new StructureXsdException(elPath.toString());
5199 }
5200
5201 break;
5202 }
5203 }
5204 }
5205
5206 protected void copyArticleImages(
5207 JournalArticle oldArticle, JournalArticle newArticle)
5208 throws Exception {
5209
5210 Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
5211
5212 XPath xPathSelector = SAXReaderUtil.createXPath(
5213 "
5214
5215 List<Node> imageNodes = xPathSelector.selectNodes(contentDoc);
5216
5217 for (Node imageNode : imageNodes) {
5218 Element imageEl = (Element)imageNode;
5219
5220 String instanceId = imageEl.attributeValue("instance-id");
5221 String name = imageEl.attributeValue("name");
5222
5223 List<Element> dynamicContentEls = imageEl.elements(
5224 "dynamic-content");
5225
5226 for (Element dynamicContentEl : dynamicContentEls) {
5227 long imageId = GetterUtil.getLong(
5228 dynamicContentEl.attributeValue("id"));
5229 String languageId = dynamicContentEl.attributeValue(
5230 "language-id");
5231
5232 Image oldImage = null;
5233
5234 try {
5235 oldImage = imageLocalService.getImage(imageId);
5236 }
5237 catch (NoSuchImageException nsie) {
5238 continue;
5239 }
5240
5241 imageId = journalArticleImageLocalService.getArticleImageId(
5242 newArticle.getGroupId(), newArticle.getArticleId(),
5243 newArticle.getVersion(), instanceId, name, languageId);
5244
5245 imageLocalService.updateImage(imageId, oldImage.getTextObj());
5246
5247 String elContent =
5248 "/image/journal/article?img_id=" + imageId + "&t=" +
5249 WebServerServletTokenUtil.getToken(imageId);
5250
5251 dynamicContentEl.setText(elContent);
5252 dynamicContentEl.addAttribute("id", String.valueOf(imageId));
5253 }
5254 }
5255
5256 newArticle.setContent(contentDoc.formattedString());
5257 }
5258
5259 protected void format(
5260 User user, long groupId, String articleId, double version,
5261 boolean incrementVersion, Element root, Map<String, byte[]> images)
5262 throws PortalException, SystemException {
5263
5264 for (Element element : root.elements()) {
5265 String elInstanceId = element.attributeValue(
5266 "instance-id", StringPool.BLANK);
5267 String elName = element.attributeValue("name", StringPool.BLANK);
5268 String elType = element.attributeValue("type", StringPool.BLANK);
5269
5270 if (elType.equals("image")) {
5271 formatImage(
5272 groupId, articleId, version, incrementVersion, element,
5273 elInstanceId, elName, images);
5274 }
5275 else if (elType.equals("text_area") || elType.equals("text") ||
5276 elType.equals("text_box")) {
5277
5278 List<Element> dynamicContentElements = element.elements(
5279 "dynamic-content");
5280
5281 for (Element dynamicContentElement : dynamicContentElements) {
5282 String dynamicContent = dynamicContentElement.getText();
5283
5284 if (Validator.isNotNull(dynamicContent)) {
5285 String contentType = ContentTypes.TEXT_PLAIN;
5286
5287 if (elType.equals("text_area")) {
5288 contentType = ContentTypes.TEXT_HTML;
5289 }
5290
5291 dynamicContent = SanitizerUtil.sanitize(
5292 user.getCompanyId(), groupId, user.getUserId(),
5293 JournalArticle.class.getName(), 0, contentType,
5294 dynamicContent);
5295
5296 dynamicContentElement.clearContent();
5297
5298 dynamicContentElement.addCDATA(dynamicContent);
5299 }
5300 }
5301 }
5302
5303 format(
5304 user, groupId, articleId, version, incrementVersion, element,
5305 images);
5306 }
5307 }
5308
5309 protected String format(
5310 User user, long groupId, String articleId, double version,
5311 boolean incrementVersion, String content, String ddmStructureKey,
5312 Map<String, byte[]> images)
5313 throws PortalException, SystemException {
5314
5315 Document document = null;
5316
5317 try {
5318 document = SAXReaderUtil.read(content);
5319
5320 Element rootElement = document.getRootElement();
5321
5322 if (Validator.isNotNull(ddmStructureKey)) {
5323 format(
5324 user, groupId, articleId, version, incrementVersion,
5325 rootElement, images);
5326 }
5327 else {
5328 List<Element> staticContentElements = rootElement.elements(
5329 "static-content");
5330
5331 for (Element staticContentElement : staticContentElements) {
5332 String staticContent = staticContentElement.getText();
5333
5334 staticContent = SanitizerUtil.sanitize(
5335 user.getCompanyId(), groupId, user.getUserId(),
5336 JournalArticle.class.getName(), 0,
5337 ContentTypes.TEXT_HTML, staticContent);
5338
5339 staticContentElement.clearContent();
5340
5341 staticContentElement.addCDATA(staticContent);
5342 }
5343 }
5344
5345 content = DDMXMLUtil.formatXML(document);
5346 }
5347 catch (DocumentException de) {
5348 _log.error(de, de);
5349 }
5350
5351 content = HtmlUtil.replaceMsWordCharacters(content);
5352
5353 return content;
5354 }
5355
5356 protected void formatImage(
5357 long groupId, String articleId, double version,
5358 boolean incrementVersion, Element el, String elInstanceId,
5359 String elName, Map<String, byte[]> images)
5360 throws PortalException, SystemException {
5361
5362 List<Element> imageContents = el.elements("dynamic-content");
5363
5364 for (Element dynamicContent : imageContents) {
5365 String elLanguage = dynamicContent.attributeValue(
5366 "language-id", StringPool.BLANK);
5367
5368 if (!elLanguage.equals(StringPool.BLANK)) {
5369 elLanguage = "_" + elLanguage;
5370 }
5371
5372 long imageId = journalArticleImageLocalService.getArticleImageId(
5373 groupId, articleId, version, elInstanceId, elName, elLanguage);
5374
5375 if (dynamicContent.getText().equals("delete") ||
5376 Validator.isNull(dynamicContent.getText())) {
5377
5378 dynamicContent.setText(StringPool.BLANK);
5379
5380 imageLocalService.deleteImage(imageId);
5381
5382 String defaultElLanguage = "";
5383
5384 if (Validator.isNull(elLanguage)) {
5385 defaultElLanguage =
5386 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
5387 }
5388
5389 long defaultImageId =
5390 journalArticleImageLocalService.getArticleImageId(
5391 groupId, articleId, version, elInstanceId, elName,
5392 defaultElLanguage);
5393
5394 imageLocalService.deleteImage(defaultImageId);
5395
5396 continue;
5397 }
5398
5399 String elContent =
5400 "/image/journal/article?img_id=" + imageId + "&t=" +
5401 WebServerServletTokenUtil.getToken(imageId);
5402
5403 byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
5404
5405 if ((bytes != null) && (bytes.length > 0)) {
5406 dynamicContent.setText(elContent);
5407 dynamicContent.addAttribute("id", String.valueOf(imageId));
5408
5409 imageLocalService.updateImage(imageId, bytes);
5410
5411 continue;
5412 }
5413
5414 if ((version > JournalArticleConstants.VERSION_DEFAULT) &&
5415 incrementVersion) {
5416
5417 double oldVersion = MathUtil.format(version - 0.1, 1, 1);
5418
5419 long oldImageId = 0;
5420
5421 if ((oldVersion >= 1) && incrementVersion) {
5422 oldImageId =
5423 journalArticleImageLocalService.getArticleImageId(
5424 groupId, articleId, oldVersion, elInstanceId,
5425 elName, elLanguage);
5426 }
5427
5428 Image oldImage = null;
5429
5430 if (oldImageId > 0) {
5431 oldImage = imageLocalService.getImage(oldImageId);
5432 }
5433
5434 if (oldImage != null) {
5435 dynamicContent.setText(elContent);
5436 dynamicContent.addAttribute("id", String.valueOf(imageId));
5437
5438 bytes = oldImage.getTextObj();
5439
5440 imageLocalService.updateImage(imageId, bytes);
5441 }
5442
5443 continue;
5444 }
5445
5446 Image image = imageLocalService.getImage(imageId);
5447
5448 if (image != null) {
5449 dynamicContent.setText(elContent);
5450 dynamicContent.addAttribute("id", String.valueOf(imageId));
5451
5452 continue;
5453 }
5454
5455 long contentImageId = GetterUtil.getLong(
5456 HttpUtil.getParameter(dynamicContent.getText(), "img_id"));
5457
5458 if (contentImageId <= 0) {
5459 contentImageId = GetterUtil.getLong(
5460 HttpUtil.getParameter(
5461 dynamicContent.getText(), "img_id", false));
5462 }
5463
5464 if (contentImageId > 0) {
5465 image = imageLocalService.getImage(contentImageId);
5466
5467 if (image != null) {
5468 dynamicContent.addAttribute(
5469 "id", String.valueOf(contentImageId));
5470
5471 continue;
5472 }
5473 }
5474
5475 String defaultElLanguage = "";
5476
5477 if (Validator.isNull(elLanguage)) {
5478 defaultElLanguage =
5479 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
5480 }
5481
5482 long defaultImageId =
5483 journalArticleImageLocalService.getArticleImageId(
5484 groupId, articleId, version, elInstanceId, elName,
5485 defaultElLanguage);
5486
5487 Image defaultImage = imageLocalService.getImage(defaultImageId);
5488
5489 if (defaultImage != null) {
5490 dynamicContent.setText(elContent);
5491 dynamicContent.addAttribute(
5492 "id", String.valueOf(defaultImageId));
5493
5494 bytes = defaultImage.getTextObj();
5495
5496 imageLocalService.updateImage(defaultImageId, bytes);
5497
5498 continue;
5499 }
5500
5501 if (Validator.isNotNull(elLanguage)) {
5502 dynamicContent.setText(StringPool.BLANK);
5503 }
5504 }
5505 }
5506
5507 protected List<ObjectValuePair<Long, Integer>> getArticleVersionStatuses(
5508 List<JournalArticle> articles) {
5509
5510 List<ObjectValuePair<Long, Integer>> dlArticleVersionStatusOVPs =
5511 new ArrayList<ObjectValuePair<Long, Integer>>(articles.size());
5512
5513 for (JournalArticle article : articles) {
5514 int status = article.getStatus();
5515
5516 if (status == WorkflowConstants.STATUS_PENDING) {
5517 status = WorkflowConstants.STATUS_DRAFT;
5518 }
5519
5520 ObjectValuePair<Long, Integer> dlFileVersionStatusOVP =
5521 new ObjectValuePair<Long, Integer>(article.getId(), status);
5522
5523 dlArticleVersionStatusOVPs.add(dlFileVersionStatusOVP);
5524 }
5525
5526 return dlArticleVersionStatusOVPs;
5527 }
5528
5529 protected long getClassTypeId(JournalArticle article) {
5530 long classTypeId = 0;
5531
5532 try {
5533 long classNameId = PortalUtil.getClassNameId(JournalArticle.class);
5534
5535 DDMStructure ddmStructure = ddmStructurePersistence.fetchByG_C_S(
5536 article.getGroupId(), classNameId, article.getStructureId());
5537
5538 if (ddmStructure == null) {
5539 Group companyGroup = groupLocalService.getCompanyGroup(
5540 article.getCompanyId());
5541
5542 ddmStructure = ddmStructurePersistence.fetchByG_C_S(
5543 companyGroup.getGroupId(), classNameId,
5544 article.getStructureId());
5545 }
5546
5547 if (ddmStructure != null) {
5548 classTypeId = ddmStructure.getStructureId();
5549 }
5550 }
5551 catch (Exception e) {
5552 _log.error(e, e);
5553 }
5554
5555 return classTypeId;
5556 }
5557
5558 protected Date[] getDateInterval(
5559 long groupId, String articleId, Date earliestDisplayDate,
5560 Date latestExpirationDate)
5561 throws SystemException {
5562
5563 Date[] dateInterval = new Date[2];
5564
5565 List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
5566 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
5567
5568 boolean expiringArticle = true;
5569
5570 if (latestExpirationDate == null) {
5571 expiringArticle = false;
5572 }
5573
5574 for (JournalArticle article : articles) {
5575 if ((earliestDisplayDate == null) ||
5576 ((article.getDisplayDate() != null) &&
5577 earliestDisplayDate.after(article.getDisplayDate()))) {
5578
5579 earliestDisplayDate = article.getDisplayDate();
5580 }
5581
5582 if (expiringArticle &&
5583 ((latestExpirationDate == null) ||
5584 ((article.getExpirationDate() != null) &&
5585 latestExpirationDate.before(article.getExpirationDate())))) {
5586
5587 latestExpirationDate = article.getExpirationDate();
5588 }
5589
5590 if (expiringArticle && (article.getExpirationDate() == null) &&
5591 (latestExpirationDate != null)) {
5592
5593 expiringArticle = false;
5594 }
5595 }
5596
5597 dateInterval[0] = earliestDisplayDate;
5598 dateInterval[1] = latestExpirationDate;
5599
5600 return dateInterval;
5601 }
5602
5603 protected String getExtraDataJSON(
5604 JournalArticle article, ServiceContext serviceContext) {
5605
5606 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
5607
5608 jsonObject.put("title", article.getTitle(serviceContext.getLocale()));
5609
5610 return jsonObject.toString();
5611 }
5612
5613 protected String getUniqueUrlTitle(
5614 long id, long groupId, String articleId, String title)
5615 throws PortalException, SystemException {
5616
5617 String urlTitle = JournalUtil.getUrlTitle(id, title);
5618
5619 for (int i = 1;; i++) {
5620 JournalArticle article = null;
5621
5622 try {
5623 article = getArticleByUrlTitle(groupId, urlTitle);
5624 }
5625 catch (NoSuchArticleException nsae) {
5626 }
5627
5628 if ((article == null) || articleId.equals(article.getArticleId())) {
5629 break;
5630 }
5631 else {
5632 String suffix = StringPool.DASH + i;
5633
5634 String prefix = urlTitle;
5635
5636 if (urlTitle.length() > suffix.length()) {
5637 prefix = urlTitle.substring(
5638 0, urlTitle.length() - suffix.length());
5639 }
5640
5641 urlTitle = prefix + suffix;
5642 }
5643 }
5644
5645 return urlTitle;
5646 }
5647
5648 protected String getUniqueUrlTitle(
5649 long id, String articleId, String title, String oldUrlTitle,
5650 ServiceContext serviceContext)
5651 throws PortalException, SystemException {
5652
5653 String serviceContextUrlTitle = ParamUtil.getString(
5654 serviceContext, "urlTitle");
5655
5656 String urlTitle = null;
5657
5658 if (Validator.isNotNull(serviceContextUrlTitle)) {
5659 urlTitle = JournalUtil.getUrlTitle(id, serviceContextUrlTitle);
5660 }
5661 else if (Validator.isNotNull(oldUrlTitle)) {
5662 return oldUrlTitle;
5663 }
5664 else {
5665 urlTitle = getUniqueUrlTitle(
5666 id, serviceContext.getScopeGroupId(), articleId, title);
5667 }
5668
5669 JournalArticle urlTitleArticle = null;
5670
5671 try {
5672 urlTitleArticle = getArticleByUrlTitle(
5673 serviceContext.getScopeGroupId(), urlTitle);
5674 }
5675 catch (NoSuchArticleException nsae) {
5676 }
5677
5678 if ((urlTitleArticle != null) &&
5679 !Validator.equals(
5680 urlTitleArticle.getArticleId(), articleId)) {
5681
5682 urlTitle = getUniqueUrlTitle(
5683 id, serviceContext.getScopeGroupId(), articleId, urlTitle);
5684 }
5685
5686 return urlTitle;
5687 }
5688
5689 protected boolean hasModifiedLatestApprovedVersion(
5690 long groupId, String articleId, double version)
5691 throws PortalException, SystemException {
5692
5693 double latestApprovedVersion;
5694
5695 try {
5696 latestApprovedVersion = getLatestVersion(
5697 groupId, articleId, WorkflowConstants.STATUS_APPROVED);
5698
5699 if (version >= latestApprovedVersion) {
5700 return true;
5701 }
5702 else {
5703 return false;
5704 }
5705 }
5706 catch (NoSuchArticleException nsae) {
5707 return true;
5708 }
5709 }
5710
5711 protected void notifySubscribers(
5712 JournalArticle article, ServiceContext serviceContext)
5713 throws PortalException, SystemException {
5714
5715 if (!article.isApproved()) {
5716 return;
5717 }
5718
5719 String articleURL = PortalUtil.getControlPanelFullURL(
5720 serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
5721
5722 if (Validator.isNull(articleURL)) {
5723 return;
5724 }
5725
5726 PortletPreferences preferences =
5727 ServiceContextUtil.getPortletPreferences(serviceContext);
5728
5729 if (preferences == null) {
5730 long ownerId = article.getGroupId();
5731 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
5732 long plid = PortletKeys.PREFS_PLID_SHARED;
5733 String portletId = PortletKeys.JOURNAL;
5734 String defaultPreferences = null;
5735
5736 preferences = portletPreferencesLocalService.getPreferences(
5737 article.getCompanyId(), ownerId, ownerType, plid, portletId,
5738 defaultPreferences);
5739 }
5740
5741 if ((article.getVersion() == 1.0) &&
5742 JournalUtil.getEmailArticleAddedEnabled(preferences)) {
5743 }
5744 else if ((article.getVersion() != 1.0) &&
5745 JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
5746 }
5747 else {
5748 return;
5749 }
5750
5751 String fromName = JournalUtil.getEmailFromName(
5752 preferences, article.getCompanyId());
5753 String fromAddress = JournalUtil.getEmailFromAddress(
5754 preferences, article.getCompanyId());
5755
5756 String subject = null;
5757 String body = null;
5758
5759 if (article.getVersion() == 1.0) {
5760 subject = JournalUtil.getEmailArticleAddedSubject(preferences);
5761 body = JournalUtil.getEmailArticleAddedBody(preferences);
5762 }
5763 else {
5764 subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
5765 body = JournalUtil.getEmailArticleUpdatedBody(preferences);
5766 }
5767
5768 SubscriptionSender subscriptionSender = new SubscriptionSender();
5769
5770 subscriptionSender.setBody(body);
5771 subscriptionSender.setCompanyId(article.getCompanyId());
5772 subscriptionSender.setContextAttributes(
5773 "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
5774 article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
5775 articleURL, "[$ARTICLE_VERSION$]", article.getVersion());
5776 subscriptionSender.setContextUserPrefix("ARTICLE");
5777 subscriptionSender.setFrom(fromAddress, fromName);
5778 subscriptionSender.setHtmlFormat(true);
5779 subscriptionSender.setMailId("journal_article", article.getId());
5780 subscriptionSender.setPortletId(PortletKeys.JOURNAL);
5781 subscriptionSender.setReplyToAddress(fromAddress);
5782 subscriptionSender.setScopeGroupId(article.getGroupId());
5783 subscriptionSender.setServiceContext(serviceContext);
5784 subscriptionSender.setSubject(subject);
5785 subscriptionSender.setUserId(article.getUserId());
5786
5787 subscriptionSender.addPersistedSubscribers(
5788 JournalArticle.class.getName(), article.getGroupId());
5789
5790 subscriptionSender.flushNotificationsAsync();
5791 }
5792
5793 protected void reindex(JournalArticle article) throws SearchException {
5794 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5795 JournalArticle.class);
5796
5797 indexer.reindex(article);
5798 }
5799
5800 protected void saveImages(
5801 boolean smallImage, long smallImageId, File smallImageFile,
5802 byte[] smallImageBytes)
5803 throws PortalException, SystemException {
5804
5805 if (smallImage) {
5806 if ((smallImageFile != null) && (smallImageBytes != null)) {
5807 imageLocalService.updateImage(smallImageId, smallImageBytes);
5808 }
5809 }
5810 else {
5811 imageLocalService.deleteImage(smallImageId);
5812 }
5813 }
5814
5815 protected void sendEmail(
5816 JournalArticle article, String articleURL,
5817 PortletPreferences preferences, String emailType,
5818 ServiceContext serviceContext)
5819 throws PortalException, SystemException {
5820
5821 if (preferences == null) {
5822 return;
5823 }
5824 else if (emailType.equals("denied") &&
5825 JournalUtil.getEmailArticleApprovalDeniedEnabled(
5826 preferences)) {
5827 }
5828 else if (emailType.equals("granted") &&
5829 JournalUtil.getEmailArticleApprovalGrantedEnabled(
5830 preferences)) {
5831 }
5832 else if (emailType.equals("requested") &&
5833 JournalUtil.getEmailArticleApprovalRequestedEnabled(
5834 preferences)) {
5835 }
5836 else if (emailType.equals("review") &&
5837 JournalUtil.getEmailArticleReviewEnabled(preferences)) {
5838 }
5839 else {
5840 return;
5841 }
5842
5843 Company company = companyPersistence.findByPrimaryKey(
5844 article.getCompanyId());
5845
5846 User user = userPersistence.findByPrimaryKey(article.getUserId());
5847
5848 articleURL +=
5849 "&groupId=" + article.getGroupId() + "&articleId=" +
5850 article.getArticleId() + "&version=" + article.getVersion();
5851
5852 String fromName = JournalUtil.getEmailFromName(
5853 preferences, article.getCompanyId());
5854 String fromAddress = JournalUtil.getEmailFromAddress(
5855 preferences, article.getCompanyId());
5856
5857 String toName = user.getFullName();
5858 String toAddress = user.getEmailAddress();
5859
5860 if (emailType.equals("requested") || emailType.equals("review")) {
5861 String tempToName = fromName;
5862 String tempToAddress = fromAddress;
5863
5864 fromName = toName;
5865 fromAddress = toAddress;
5866
5867 toName = tempToName;
5868 toAddress = tempToAddress;
5869 }
5870
5871 String subject = null;
5872 String body = null;
5873
5874 if (emailType.equals("denied")) {
5875 subject = JournalUtil.getEmailArticleApprovalDeniedSubject(
5876 preferences);
5877 body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
5878 }
5879 else if (emailType.equals("granted")) {
5880 subject = JournalUtil.getEmailArticleApprovalGrantedSubject(
5881 preferences);
5882 body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
5883 }
5884 else if (emailType.equals("requested")) {
5885 subject = JournalUtil.getEmailArticleApprovalRequestedSubject(
5886 preferences);
5887 body = JournalUtil.getEmailArticleApprovalRequestedBody(
5888 preferences);
5889 }
5890 else if (emailType.equals("review")) {
5891 subject = JournalUtil.getEmailArticleReviewSubject(preferences);
5892 body = JournalUtil.getEmailArticleReviewBody(preferences);
5893 }
5894
5895 SubscriptionSender subscriptionSender = new SubscriptionSender();
5896
5897 subscriptionSender.setBody(body);
5898 subscriptionSender.setCompanyId(company.getCompanyId());
5899 subscriptionSender.setContextAttributes(
5900 "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
5901 article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
5902 articleURL, "[$ARTICLE_USER_NAME$]", article.getUserName(),
5903 "[$ARTICLE_VERSION$]", article.getVersion());
5904 subscriptionSender.setContextUserPrefix("ARTICLE");
5905 subscriptionSender.setFrom(fromAddress, fromName);
5906 subscriptionSender.setHtmlFormat(true);
5907 subscriptionSender.setMailId("journal_article", article.getId());
5908 subscriptionSender.setPortletId(PortletKeys.JOURNAL);
5909 subscriptionSender.setScopeGroupId(article.getGroupId());
5910 subscriptionSender.setServiceContext(serviceContext);
5911 subscriptionSender.setSubject(subject);
5912 subscriptionSender.setUserId(article.getUserId());
5913
5914 subscriptionSender.addRuntimeSubscribers(toAddress, toName);
5915
5916 subscriptionSender.flushNotificationsAsync();
5917 }
5918
5919 protected void updateDDMStructureXSD(
5920 long ddmStructureId, String content, ServiceContext serviceContext)
5921 throws PortalException, SystemException {
5922
5923 try {
5924 Document document = SAXReaderUtil.read(content);
5925
5926 Element rootElement = document.getRootElement();
5927
5928 List<Element> elements = rootElement.elements();
5929
5930 for (Element element : elements) {
5931 String fieldName = element.attributeValue(
5932 "name", StringPool.BLANK);
5933
5934 List<Element> dynamicContentElements = element.elements(
5935 "dynamic-content");
5936
5937 for (Element dynamicContentElement : dynamicContentElements) {
5938 String value = dynamicContentElement.getText();
5939
5940 ddmStructureLocalService.updateXSDFieldMetadata(
5941 ddmStructureId, fieldName,
5942 FieldConstants.PREDEFINED_VALUE, value, serviceContext);
5943 }
5944 }
5945 }
5946 catch (DocumentException de) {
5947 throw new SystemException(de);
5948 }
5949 }
5950
5951 protected void updatePreviousApprovedArticle(JournalArticle article)
5952 throws PortalException, SystemException {
5953
5954 List<JournalArticle> approvedArticles =
5955 journalArticlePersistence.findByG_A_ST(
5956 article.getGroupId(), article.getArticleId(),
5957 WorkflowConstants.STATUS_APPROVED, 0, 2);
5958
5959 if (approvedArticles.isEmpty() ||
5960 ((approvedArticles.size() == 1) &&
5961 (article.getStatus() == WorkflowConstants.STATUS_APPROVED))) {
5962
5963 if (article.isIndexable()) {
5964 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
5965 JournalArticle.class);
5966
5967 indexer.delete(article);
5968 }
5969
5970 assetEntryLocalService.updateVisible(
5971 JournalArticle.class.getName(), article.getResourcePrimKey(),
5972 false);
5973 }
5974 else {
5975 JournalArticle previousApprovedArticle = approvedArticles.get(0);
5976
5977 if (article.getStatus() == WorkflowConstants.STATUS_APPROVED) {
5978 previousApprovedArticle = approvedArticles.get(1);
5979 }
5980
5981 Date[] dateInterval = getDateInterval(
5982 previousApprovedArticle.getGroupId(),
5983 previousApprovedArticle.getArticleId(),
5984 previousApprovedArticle.getDisplayDate(),
5985 previousApprovedArticle.getExpirationDate());
5986
5987 Date displayDate = dateInterval[0];
5988 Date expirationDate = dateInterval[1];
5989
5990 AssetEntry assetEntry = assetEntryLocalService.updateEntry(
5991 JournalArticle.class.getName(), article.getResourcePrimKey(),
5992 displayDate, expirationDate, true);
5993
5994 assetEntry.setModifiedDate(
5995 previousApprovedArticle.getModifiedDate());
5996
5997 assetEntryPersistence.update(assetEntry);
5998
5999 if (article.isIndexable()) {
6000 reindex(previousApprovedArticle);
6001 }
6002 }
6003 }
6004
6005 protected void updateUrlTitles(
6006 long groupId, String articleId, String urlTitle)
6007 throws SystemException {
6008
6009 List<JournalArticle> articles = journalArticlePersistence.findByG_A(
6010 groupId, articleId);
6011
6012 for (JournalArticle article : articles) {
6013 if (!article.getUrlTitle().equals(urlTitle)) {
6014 article.setUrlTitle(urlTitle);
6015
6016 journalArticlePersistence.update(article);
6017 }
6018 }
6019 }
6020
6021 protected void validate(
6022 long companyId, long groupId, long classNameId,
6023 Map<Locale, String> titleMap, String content, String type,
6024 String ddmStructureKey, String ddmTemplateKey, Date expirationDate,
6025 boolean smallImage, String smallImageURL, File smallImageFile,
6026 byte[] smallImageBytes)
6027 throws PortalException, SystemException {
6028
6029 Locale articleDefaultLocale = LocaleUtil.fromLanguageId(
6030 LocalizationUtil.getDefaultLocale(content));
6031
6032 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
6033
6034 if (!ArrayUtil.contains(availableLocales, articleDefaultLocale)) {
6035 LocaleException le = new LocaleException(
6036 "The locale " + articleDefaultLocale +
6037 " is not available in company " + companyId);
6038
6039 Locale[] sourceAvailableLocales = {articleDefaultLocale};
6040
6041 le.setSourceAvailableLocales(sourceAvailableLocales);
6042 le.setTargetAvailableLocales(availableLocales);
6043
6044 throw le;
6045 }
6046
6047 if ((classNameId == JournalArticleConstants.CLASSNAME_ID_DEFAULT) &&
6048 (titleMap.isEmpty() ||
6049 Validator.isNull(titleMap.get(articleDefaultLocale)))) {
6050
6051 throw new ArticleTitleException();
6052 }
6053 else if (Validator.isNull(type)) {
6054 throw new ArticleTypeException();
6055 }
6056
6057 validateContent(content);
6058
6059 if (Validator.isNotNull(ddmStructureKey)) {
6060 Group companyGroup = groupLocalService.getCompanyGroup(companyId);
6061
6062 DDMStructure ddmStructure = null;
6063
6064 try {
6065 ddmStructure = ddmStructurePersistence.findByG_C_S(
6066 groupId, PortalUtil.getClassNameId(JournalArticle.class),
6067 ddmStructureKey);
6068 }
6069 catch (NoSuchStructureException nsse) {
6070 ddmStructure = ddmStructurePersistence.findByG_C_S(
6071 companyGroup.getGroupId(),
6072 PortalUtil.getClassNameId(JournalArticle.class),
6073 ddmStructureKey);
6074 }
6075
6076 DDMTemplate ddmTemplate = null;
6077
6078 if (Validator.isNotNull(ddmTemplateKey)) {
6079 try {
6080 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
6081 groupId, PortalUtil.getClassNameId(DDMStructure.class),
6082 ddmTemplateKey);
6083 }
6084 catch (NoSuchTemplateException nste) {
6085 ddmTemplate = ddmTemplatePersistence.findByG_C_T(
6086 companyGroup.getGroupId(),
6087 PortalUtil.getClassNameId(DDMStructure.class),
6088 ddmTemplateKey);
6089 }
6090
6091 if (ddmTemplate.getClassPK() != ddmStructure.getStructureId()) {
6092 throw new NoSuchTemplateException();
6093 }
6094 }
6095 else if (classNameId ==
6096 JournalArticleConstants.CLASSNAME_ID_DEFAULT) {
6097
6098 throw new NoSuchTemplateException();
6099 }
6100 }
6101
6102 if ((expirationDate != null) && expirationDate.before(new Date()) &&
6103 !ExportImportThreadLocal.isImportInProcess()) {
6104
6105 throw new ArticleExpirationDateException();
6106 }
6107
6108 String[] imageExtensions = PrefsPropsUtil.getStringArray(
6109 PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
6110
6111 if (smallImage && Validator.isNull(smallImageURL) &&
6112 (smallImageFile != null) && (smallImageBytes != null)) {
6113
6114 String smallImageName = smallImageFile.getName();
6115
6116 if (smallImageName != null) {
6117 boolean validSmallImageExtension = false;
6118
6119 for (String _imageExtension : imageExtensions) {
6120 if (StringPool.STAR.equals(_imageExtension) ||
6121 StringUtil.endsWith(smallImageName, _imageExtension)) {
6122
6123 validSmallImageExtension = true;
6124
6125 break;
6126 }
6127 }
6128
6129 if (!validSmallImageExtension) {
6130 throw new ArticleSmallImageNameException(smallImageName);
6131 }
6132 }
6133
6134 long smallImageMaxSize = PrefsPropsUtil.getLong(
6135 PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
6136
6137 if ((smallImageMaxSize > 0) &&
6138 ((smallImageBytes == null) ||
6139 (smallImageBytes.length > smallImageMaxSize))) {
6140
6141 throw new ArticleSmallImageSizeException();
6142 }
6143 }
6144 }
6145
6146 protected void validate(
6147 long companyId, long groupId, long classNameId, String articleId,
6148 boolean autoArticleId, double version, Map<Locale, String> titleMap,
6149 String content, String type, String ddmStructureKey,
6150 String ddmTemplateKey, Date expirationDate, boolean smallImage,
6151 String smallImageURL, File smallImageFile, byte[] smallImageBytes)
6152 throws PortalException, SystemException {
6153
6154 if (!autoArticleId) {
6155 validate(articleId);
6156 }
6157
6158 JournalArticle article = journalArticlePersistence.fetchByG_A_V(
6159 groupId, articleId, version);
6160
6161 if (article != null) {
6162 throw new DuplicateArticleIdException();
6163 }
6164
6165 validate(
6166 companyId, groupId, classNameId, titleMap, content, type,
6167 ddmStructureKey, ddmTemplateKey, expirationDate, smallImage,
6168 smallImageURL, smallImageFile, smallImageBytes);
6169 }
6170
6171 protected void validate(String articleId) throws PortalException {
6172 if (Validator.isNull(articleId) ||
6173 (articleId.indexOf(CharPool.SPACE) != -1)) {
6174
6175 throw new ArticleIdException();
6176 }
6177 }
6178
6179 protected void validateContent(String content) throws PortalException {
6180 if (Validator.isNull(content)) {
6181 throw new ArticleContentException("Content is null");
6182 }
6183
6184 try {
6185 SAXReaderUtil.read(content);
6186 }
6187 catch (DocumentException de) {
6188 if (_log.isDebugEnabled()) {
6189 _log.debug("Invalid content:\n" + content);
6190 }
6191
6192 throw new ArticleContentException(
6193 "Unable to read content with an XML parser", de);
6194 }
6195 }
6196
6197 private static final long _JOURNAL_ARTICLE_CHECK_INTERVAL =
6198 PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
6199
6200 private static Log _log = LogFactoryUtil.getLog(
6201 JournalArticleLocalServiceImpl.class);
6202
6203 private Date _previousCheckDate;
6204
6205 }