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