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