1
22
23 package com.liferay.portlet.journal.service.impl;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.mail.MailMessage;
28 import com.liferay.portal.kernel.search.Hits;
29 import com.liferay.portal.kernel.servlet.ImageServletTokenUtil;
30 import com.liferay.portal.kernel.util.ContentTypes;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.LocaleUtil;
33 import com.liferay.portal.kernel.util.OrderByComparator;
34 import com.liferay.portal.kernel.util.StringMaker;
35 import com.liferay.portal.kernel.util.StringPool;
36 import com.liferay.portal.kernel.util.StringUtil;
37 import com.liferay.portal.kernel.util.Validator;
38 import com.liferay.portal.lucene.LuceneFields;
39 import com.liferay.portal.lucene.LuceneUtil;
40 import com.liferay.portal.model.Company;
41 import com.liferay.portal.model.Image;
42 import com.liferay.portal.model.User;
43 import com.liferay.portal.model.impl.ResourceImpl;
44 import com.liferay.portal.service.impl.ImageLocalUtil;
45 import com.liferay.portal.servlet.filters.layoutcache.LayoutCacheUtil;
46 import com.liferay.portal.theme.ThemeDisplay;
47 import com.liferay.portal.util.PortalUtil;
48 import com.liferay.portal.util.PortletKeys;
49 import com.liferay.portal.util.PropsUtil;
50 import com.liferay.portlet.journal.ArticleContentException;
51 import com.liferay.portlet.journal.ArticleDisplayDateException;
52 import com.liferay.portlet.journal.ArticleExpirationDateException;
53 import com.liferay.portlet.journal.ArticleIdException;
54 import com.liferay.portlet.journal.ArticleReviewDateException;
55 import com.liferay.portlet.journal.ArticleSmallImageNameException;
56 import com.liferay.portlet.journal.ArticleSmallImageSizeException;
57 import com.liferay.portlet.journal.ArticleTitleException;
58 import com.liferay.portlet.journal.ArticleTypeException;
59 import com.liferay.portlet.journal.DuplicateArticleIdException;
60 import com.liferay.portlet.journal.NoSuchArticleException;
61 import com.liferay.portlet.journal.NoSuchArticleResourceException;
62 import com.liferay.portlet.journal.NoSuchTemplateException;
63 import com.liferay.portlet.journal.StructureXsdException;
64 import com.liferay.portlet.journal.job.CheckArticleJob;
65 import com.liferay.portlet.journal.model.JournalArticle;
66 import com.liferay.portlet.journal.model.JournalArticleDisplay;
67 import com.liferay.portlet.journal.model.JournalStructure;
68 import com.liferay.portlet.journal.model.JournalTemplate;
69 import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
70 import com.liferay.portlet.journal.model.impl.JournalArticleImpl;
71 import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
72 import com.liferay.portlet.journal.util.Indexer;
73 import com.liferay.portlet.journal.util.JournalUtil;
74 import com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator;
75 import com.liferay.portlet.journalcontent.util.JournalContentUtil;
76 import com.liferay.util.FileUtil;
77 import com.liferay.util.Html;
78 import com.liferay.util.LocalizationUtil;
79 import com.liferay.util.MathUtil;
80 import com.liferay.util.lucene.HitsImpl;
81
82 import java.io.File;
83 import java.io.IOException;
84 import java.io.StringReader;
85
86 import java.util.Collections;
87 import java.util.Date;
88 import java.util.HashSet;
89 import java.util.Iterator;
90 import java.util.List;
91 import java.util.Map;
92 import java.util.Set;
93
94 import javax.mail.internet.InternetAddress;
95
96 import javax.portlet.PortletPreferences;
97
98 import org.apache.commons.logging.Log;
99 import org.apache.commons.logging.LogFactory;
100 import org.apache.lucene.index.IndexWriter;
101 import org.apache.lucene.search.BooleanClause;
102 import org.apache.lucene.search.BooleanQuery;
103 import org.apache.lucene.search.Searcher;
104 import org.apache.lucene.search.Sort;
105 import org.apache.lucene.search.SortField;
106
107 import org.dom4j.Document;
108 import org.dom4j.DocumentException;
109 import org.dom4j.DocumentFactory;
110 import org.dom4j.DocumentHelper;
111 import org.dom4j.Element;
112 import org.dom4j.XPath;
113 import org.dom4j.io.SAXReader;
114
115
122 public class JournalArticleLocalServiceImpl
123 extends JournalArticleLocalServiceBaseImpl {
124
125 public JournalArticle addArticle(
126 long userId, String articleId, boolean autoArticleId, long plid,
127 String title, String description, String content, String type,
128 String structureId, String templateId, int displayDateMonth,
129 int displayDateDay, int displayDateYear, int displayDateHour,
130 int displayDateMinute, int expirationDateMonth,
131 int expirationDateDay, int expirationDateYear,
132 int expirationDateHour, int expirationDateMinute,
133 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
134 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
135 boolean neverReview, boolean indexable, boolean smallImage,
136 String smallImageURL, File smallFile, Map images, String articleURL,
137 PortletPreferences prefs, String[] tagsEntries,
138 boolean addCommunityPermissions, boolean addGuestPermissions)
139 throws PortalException, SystemException {
140
141 return addArticle(
142 null, userId, articleId, autoArticleId, plid, title, description,
143 content, type, structureId, templateId, displayDateMonth,
144 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
145 expirationDateMonth, expirationDateDay, expirationDateYear,
146 expirationDateHour, expirationDateMinute, neverExpire,
147 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
148 reviewDateMinute, neverReview, indexable, smallImage, smallImageURL,
149 smallFile, images, articleURL, prefs, tagsEntries,
150 Boolean.valueOf(addCommunityPermissions),
151 Boolean.valueOf(addGuestPermissions), null, null);
152 }
153
154 public JournalArticle addArticle(
155 String uuid, long userId, String articleId, boolean autoArticleId,
156 long plid, String title, String description, String content,
157 String type, String structureId, String templateId,
158 int displayDateMonth, int displayDateDay, int displayDateYear,
159 int displayDateHour, int displayDateMinute, int expirationDateMonth,
160 int expirationDateDay, int expirationDateYear,
161 int expirationDateHour, int expirationDateMinute,
162 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
163 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
164 boolean neverReview, boolean indexable, boolean smallImage,
165 String smallImageURL, File smallFile, Map images, String articleURL,
166 PortletPreferences prefs, String[] tagsEntries,
167 boolean addCommunityPermissions, boolean addGuestPermissions)
168 throws PortalException, SystemException {
169
170 return addArticle(
171 uuid, userId, articleId, autoArticleId, plid, title, description,
172 content, type, structureId, templateId, displayDateMonth,
173 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
174 expirationDateMonth, expirationDateDay, expirationDateYear,
175 expirationDateHour, expirationDateMinute, neverExpire,
176 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
177 reviewDateMinute, neverReview, indexable, smallImage, smallImageURL,
178 smallFile, images, articleURL, prefs, tagsEntries,
179 Boolean.valueOf(addCommunityPermissions),
180 Boolean.valueOf(addGuestPermissions), null, null);
181 }
182
183 public JournalArticle addArticle(
184 long userId, String articleId, boolean autoArticleId, long plid,
185 String title, String description, String content, String type,
186 String structureId, String templateId, int displayDateMonth,
187 int displayDateDay, int displayDateYear, int displayDateHour,
188 int displayDateMinute, int expirationDateMonth,
189 int expirationDateDay, int expirationDateYear,
190 int expirationDateHour, int expirationDateMinute,
191 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
192 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
193 boolean neverReview, boolean indexable, boolean smallImage,
194 String smallImageURL, File smallFile, Map images, String articleURL,
195 PortletPreferences prefs, String[] tagsEntries,
196 String[] communityPermissions, String[] guestPermissions)
197 throws PortalException, SystemException {
198
199 return addArticle(
200 null, userId, articleId, autoArticleId, plid, title, description,
201 content, type, structureId, templateId, displayDateMonth,
202 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
203 expirationDateMonth, expirationDateDay, expirationDateYear,
204 expirationDateHour, expirationDateMinute, neverExpire,
205 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
206 reviewDateMinute, neverReview, indexable, smallImage, smallImageURL,
207 smallFile, images, articleURL, prefs, tagsEntries, null, null,
208 communityPermissions, guestPermissions);
209 }
210
211 public JournalArticle addArticle(
212 String uuid, long userId, String articleId, boolean autoArticleId,
213 long plid, String title, String description, String content,
214 String type, String structureId, String templateId,
215 int displayDateMonth, int displayDateDay, int displayDateYear,
216 int displayDateHour, int displayDateMinute, int expirationDateMonth,
217 int expirationDateDay, int expirationDateYear,
218 int expirationDateHour, int expirationDateMinute,
219 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
220 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
221 boolean neverReview, boolean indexable, boolean smallImage,
222 String smallImageURL, File smallFile, Map images, String articleURL,
223 PortletPreferences prefs, String[] tagsEntries,
224 Boolean addCommunityPermissions, Boolean addGuestPermissions,
225 String[] communityPermissions, String[] guestPermissions)
226 throws PortalException, SystemException {
227
228 long groupId = PortalUtil.getPortletGroupId(plid);
229
230 return addArticleToGroup(
231 uuid, userId, articleId, autoArticleId, groupId, title, description,
232 content, type, structureId, templateId, displayDateMonth,
233 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
234 expirationDateMonth, expirationDateDay, expirationDateYear,
235 expirationDateHour, expirationDateMinute, neverExpire,
236 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
237 reviewDateMinute, neverReview, indexable, smallImage, smallImageURL,
238 smallFile, images, articleURL, prefs, tagsEntries,
239 addCommunityPermissions, addGuestPermissions, communityPermissions,
240 guestPermissions);
241 }
242
243 public JournalArticle addArticleToGroup(
244 String uuid, long userId, String articleId, boolean autoArticleId,
245 long groupId, String title, String description, String content,
246 String type, String structureId, String templateId,
247 int displayDateMonth, int displayDateDay, int displayDateYear,
248 int displayDateHour, int displayDateMinute, int expirationDateMonth,
249 int expirationDateDay, int expirationDateYear,
250 int expirationDateHour, int expirationDateMinute,
251 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
252 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
253 boolean neverReview, boolean indexable, boolean smallImage,
254 String smallImageURL, File smallFile, Map images, String articleURL,
255 PortletPreferences prefs, String[] tagsEntries,
256 Boolean addCommunityPermissions, Boolean addGuestPermissions,
257 String[] communityPermissions, String[] guestPermissions)
258 throws PortalException, SystemException {
259
260
262 User user = userPersistence.findByPrimaryKey(userId);
263 articleId = articleId.trim().toUpperCase();
264 Date now = new Date();
265
266 Date displayDate = PortalUtil.getDate(
267 displayDateMonth, displayDateDay, displayDateYear,
268 displayDateHour, displayDateMinute, user.getTimeZone(),
269 new ArticleDisplayDateException());
270
271 Date expirationDate = null;
272
273 if (!neverExpire) {
274 expirationDate = PortalUtil.getDate(
275 expirationDateMonth, expirationDateDay, expirationDateYear,
276 expirationDateHour, expirationDateMinute, user.getTimeZone(),
277 new ArticleExpirationDateException());
278 }
279
280 Date reviewDate = null;
281
282 if (!neverReview) {
283 reviewDate = PortalUtil.getDate(
284 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
285 reviewDateMinute, user.getTimeZone(),
286 new ArticleReviewDateException());
287 }
288
289 byte[] smallBytes = null;
290
291 try {
292 smallBytes = FileUtil.getBytes(smallFile);
293 }
294 catch (IOException ioe) {
295 }
296
297 validate(
298 groupId, articleId, autoArticleId, title, content, type,
299 structureId, templateId, smallImage, smallImageURL, smallFile,
300 smallBytes);
301
302 if (autoArticleId) {
303 articleId = String.valueOf(counterLocalService.increment());
304 }
305
306 long id = counterLocalService.increment();
307
308 long resourcePrimKey =
309 journalArticleResourceLocalService.getArticleResourcePrimKey(
310 groupId, articleId);
311
312 JournalArticle article = journalArticlePersistence.create(id);
313
314 content = format(
315 groupId, articleId, article.getVersion(), false, content,
316 structureId, images);
317
318 article.setUuid(uuid);
319 article.setResourcePrimKey(resourcePrimKey);
320 article.setGroupId(groupId);
321 article.setCompanyId(user.getCompanyId());
322 article.setUserId(user.getUserId());
323 article.setUserName(user.getFullName());
324 article.setCreateDate(now);
325 article.setModifiedDate(now);
326 article.setArticleId(articleId);
327 article.setVersion(JournalArticleImpl.DEFAULT_VERSION);
328 article.setTitle(title);
329 article.setDescription(description);
330 article.setContent(content);
331 article.setType(type);
332 article.setStructureId(structureId);
333 article.setTemplateId(templateId);
334 article.setDisplayDate(displayDate);
335 article.setApproved(false);
336
337 if ((expirationDate == null) || expirationDate.after(now)) {
338 article.setExpired(false);
339 }
340 else {
341 article.setExpired(true);
342 }
343
344 article.setExpirationDate(expirationDate);
345 article.setReviewDate(reviewDate);
346 article.setIndexable(indexable);
347 article.setSmallImage(smallImage);
348 article.setSmallImageId(counterLocalService.increment());
349 article.setSmallImageURL(smallImageURL);
350
351 journalArticlePersistence.update(article);
352
353
355 saveImages(
356 smallImage, article.getSmallImageId(), smallFile, smallBytes);
357
358
360 if ((addCommunityPermissions != null) &&
361 (addGuestPermissions != null)) {
362
363 addArticleResources(
364 article, addCommunityPermissions.booleanValue(),
365 addGuestPermissions.booleanValue());
366 }
367 else {
368 addArticleResources(
369 article, communityPermissions, guestPermissions);
370 }
371
372
374 updateTagsAsset(userId, article, tagsEntries);
375
376
378 sendEmail(article, articleURL, prefs, "requested");
379
380 return article;
381 }
382
383 public void addArticleResources(
384 long groupId, String articleId, boolean addCommunityPermissions,
385 boolean addGuestPermissions)
386 throws PortalException, SystemException {
387
388 JournalArticle article = getLatestArticle(groupId, articleId);
389
390 addArticleResources(
391 article, addCommunityPermissions, addGuestPermissions);
392 }
393
394 public void addArticleResources(
395 JournalArticle article, boolean addCommunityPermissions,
396 boolean addGuestPermissions)
397 throws PortalException, SystemException {
398
399 resourceLocalService.addResources(
400 article.getCompanyId(), article.getGroupId(),
401 article.getUserId(), JournalArticle.class.getName(),
402 article.getResourcePrimKey(), false, addCommunityPermissions,
403 addGuestPermissions);
404 }
405
406 public void addArticleResources(
407 long groupId, String articleId, String[] communityPermissions,
408 String[] guestPermissions)
409 throws PortalException, SystemException {
410
411 JournalArticle article = getLatestArticle(groupId, articleId);
412
413 addArticleResources(article, communityPermissions, guestPermissions);
414 }
415
416 public void addArticleResources(
417 JournalArticle article, String[] communityPermissions,
418 String[] guestPermissions)
419 throws PortalException, SystemException {
420
421 resourceLocalService.addModelResources(
422 article.getCompanyId(), article.getGroupId(),
423 article.getUserId(), JournalArticle.class.getName(),
424 article.getResourcePrimKey(), communityPermissions,
425 guestPermissions);
426 }
427
428 public JournalArticle approveArticle(
429 long userId, long groupId, String articleId, double version,
430 String articleURL, PortletPreferences prefs)
431 throws PortalException, SystemException {
432
433
435 User user = userPersistence.findByPrimaryKey(userId);
436 Date now = new Date();
437
438 JournalArticle article = journalArticlePersistence.findByG_A_V(
439 groupId, articleId, version);
440
441 article.setModifiedDate(now);
442 article.setApproved(true);
443 article.setApprovedByUserId(user.getUserId());
444 article.setApprovedByUserName(user.getFullName());
445 article.setApprovedDate(now);
446
447 journalArticlePersistence.update(article);
448
449
451 sendEmail(article, articleURL, prefs, "granted");
452
453
455 try {
456 if (article.isIndexable()) {
457 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
458 JournalArticle.class.getName(),
459 article.getResourcePrimKey());
460
461 Indexer.updateArticle(
462 article.getCompanyId(), article.getGroupId(),
463 article.getArticleId(), article.getVersion(),
464 article.getTitle(), article.getDescription(),
465 article.getContent(), article.getType(),
466 article.getDisplayDate(), tagsEntries);
467 }
468 }
469 catch (IOException ioe) {
470 _log.error("Indexing " + article.getId(), ioe);
471 }
472
473 return article;
474 }
475
476 public JournalArticle checkArticleResourcePrimKey(
477 long groupId, String articleId, double version)
478 throws PortalException, SystemException {
479
480 JournalArticle article = journalArticlePersistence.findByG_A_V(
481 groupId, articleId, version);
482
483 if (article.getResourcePrimKey() > 0) {
484 return article;
485 }
486
487 long resourcePrimKey =
488 journalArticleResourceLocalService.getArticleResourcePrimKey(
489 groupId, articleId);
490
491 article.setResourcePrimKey(resourcePrimKey);
492
493 journalArticlePersistence.update(article);
494
495 return article;
496 }
497
498 public void checkArticles() throws PortalException, SystemException {
499 Date now = new Date();
500
501 List articles = journalArticleFinder.findByExpirationDate(
502 Boolean.FALSE, now,
503 new Date(now.getTime() - CheckArticleJob.INTERVAL));
504
505 if (_log.isDebugEnabled()) {
506 _log.debug("Expiring " + articles.size() + " articles");
507 }
508
509 Set companies = new HashSet();
510
511 for (int i = 0; i < articles.size(); i++) {
512 JournalArticle article = (JournalArticle)articles.get(i);
513
514 article.setApproved(false);
515 article.setExpired(true);
516
517 journalArticlePersistence.update(article);
518
519 try {
520 if (article.isIndexable()) {
521 Indexer.deleteArticle(
522 article.getCompanyId(), article.getArticleId());
523 }
524 }
525 catch (IOException ioe) {
526 _log.error("Removing index " + article.getId(), ioe);
527 }
528
529 JournalContentUtil.clearCache(
530 article.getGroupId(), article.getArticleId(),
531 article.getTemplateId());
532
533 companies.add(new Long(article.getCompanyId()));
534 }
535
536 Iterator itr = companies.iterator();
537
538 while (itr.hasNext()) {
539 long companyId = ((Long)itr.next()).longValue();
540
541 LayoutCacheUtil.clearCache(companyId);
542 }
543
544 articles = journalArticleFinder.findByReviewDate(
545 now, new Date(now.getTime() - CheckArticleJob.INTERVAL));
546
547 if (_log.isDebugEnabled()) {
548 _log.debug(
549 "Sending review notifications for " + articles.size() +
550 " articles");
551 }
552
553 for (int i = 0; i < articles.size(); i++) {
554 JournalArticle article = (JournalArticle)articles.get(i);
555
556 Date reviewDate = article.getReviewDate();
557
558 if (reviewDate != null) {
559 long diff = reviewDate.getTime() - now.getTime();
560
561 if ((diff > 0) && (diff < CheckArticleJob.INTERVAL)) {
562 String articleURL = StringPool.BLANK;
563
564 long ownerId = article.getGroupId();
565 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
566 long plid = PortletKeys.PREFS_PLID_SHARED;
567 String portletId = PortletKeys.JOURNAL;
568
569 PortletPreferences prefs =
570 portletPreferencesLocalService.getPreferences(
571 article.getCompanyId(), ownerId, ownerType, plid,
572 portletId);
573
574 sendEmail(article, articleURL, prefs, "review");
575 }
576 }
577 }
578 }
579
580 public void checkNewLine(long groupId, String articleId, double version)
581 throws PortalException, SystemException {
582
583 JournalArticle article = journalArticlePersistence.findByG_A_V(
584 groupId, articleId, version);
585
586 String content = GetterUtil.getString(article.getContent());
587
588 if (content.indexOf("\\n") != -1) {
589 content = StringUtil.replace(
590 content,
591 new String[] {"\\n", "\\r"},
592 new String[] {"\n", "\r"});
593
594 article.setContent(content);
595
596 journalArticlePersistence.update(article);
597 }
598 }
599
600 public void checkStructure(long groupId, String articleId, double version)
601 throws PortalException, SystemException {
602
603 JournalArticle article = journalArticlePersistence.findByG_A_V(
604 groupId, articleId, version);
605
606 if (Validator.isNull(article.getStructureId())) {
607 return;
608 }
609
610 try {
611 checkStructure(article);
612 }
613 catch (DocumentException de) {
614 _log.error(de, de);
615 }
616 }
617
618 public void deleteArticle(
619 long groupId, String articleId, double version, String articleURL,
620 PortletPreferences prefs)
621 throws PortalException, SystemException {
622
623 JournalArticle article = journalArticlePersistence.findByG_A_V(
624 groupId, articleId, version);
625
626 deleteArticle(article, articleURL, prefs);
627 }
628
629 public void deleteArticle(
630 JournalArticle article, String articleURL, PortletPreferences prefs)
631 throws PortalException, SystemException {
632
633
635 try {
636 if (article.isApproved() && article.isIndexable()) {
637 Indexer.deleteArticle(
638 article.getCompanyId(), article.getArticleId());
639 }
640 }
641 catch (IOException ioe) {
642 _log.error("Deleting index " + article.getPrimaryKey(), ioe);
643 }
644
645
647 if ((prefs != null) && !article.isApproved() &&
648 isLatestVersion(
649 article.getGroupId(), article.getArticleId(),
650 article.getVersion())) {
651
652 sendEmail(article, articleURL, prefs, "denied");
653 }
654
655
657 tagsAssetLocalService.deleteAsset(
658 JournalArticle.class.getName(), article.getResourcePrimKey());
659
660
662 ratingsStatsLocalService.deleteStats(
663 JournalArticle.class.getName(), article.getResourcePrimKey());
664
665
667 mbMessageLocalService.deleteDiscussionMessages(
668 JournalArticle.class.getName(), article.getResourcePrimKey());
669
670
672 journalContentSearchLocalService.deleteArticleContentSearches(
673 article.getGroupId(), article.getArticleId());
674
675
677 journalArticleImageLocalService.deleteImages(
678 article.getGroupId(), article.getArticleId(), article.getVersion());
679
680
682 ImageLocalUtil.deleteImage(article.getSmallImageId());
683
684
686 if (journalArticlePersistence.countByG_A(
687 article.getGroupId(), article.getArticleId()) == 1) {
688
689 resourceLocalService.deleteResource(
690 article.getCompanyId(), JournalArticle.class.getName(),
691 ResourceImpl.SCOPE_INDIVIDUAL, article.getResourcePrimKey());
692 }
693
694
696 if (journalArticlePersistence.countByG_A(
697 article.getGroupId(), article.getArticleId()) == 1) {
698
699 try {
700 journalArticleResourceLocalService.deleteArticleResource(
701 article.getGroupId(), article.getArticleId());
702 }
703 catch (NoSuchArticleResourceException nsare) {
704 }
705 }
706
707
709 journalArticlePersistence.remove(article.getPrimaryKey());
710 }
711
712 public void deleteArticles(long groupId)
713 throws PortalException, SystemException {
714
715 Iterator itr = journalArticlePersistence.findByGroupId(
716 groupId).iterator();
717
718 while (itr.hasNext()) {
719 JournalArticle article = (JournalArticle)itr.next();
720
721 deleteArticle(article, null, null);
722 }
723 }
724
725 public void expireArticle(
726 long groupId, String articleId, double version, String articleURL,
727 PortletPreferences prefs)
728 throws PortalException, SystemException {
729
730 JournalArticle article = journalArticlePersistence.findByG_A_V(
731 groupId, articleId, version);
732
733 expireArticle(article, articleURL, prefs);
734 }
735
736 public void expireArticle(
737 JournalArticle article, String articleURL, PortletPreferences prefs)
738 throws PortalException, SystemException {
739
740
742 if ((prefs != null) && !article.isApproved() &&
743 isLatestVersion(
744 article.getGroupId(), article.getArticleId(),
745 article.getVersion())) {
746
747 sendEmail(article, articleURL, prefs, "denied");
748 }
749
750
752 article.setExpirationDate(new Date());
753
754 article.setApproved(false);
755 article.setExpired(true);
756
757 journalArticlePersistence.update(article);
758
759
761 try {
762 if (article.isIndexable()) {
763 Indexer.deleteArticle(
764 article.getCompanyId(), article.getArticleId());
765 }
766 }
767 catch (IOException ioe) {
768 _log.error("Removing index " + article.getId(), ioe);
769 }
770 }
771
772 public JournalArticle getArticle(long id)
773 throws PortalException, SystemException {
774
775 return journalArticlePersistence.findByPrimaryKey(id);
776 }
777
778 public JournalArticle getArticle(long groupId, String articleId)
779 throws PortalException, SystemException {
780
781
784 try {
785 return getLatestArticle(groupId, articleId, Boolean.TRUE);
786 }
787 catch (NoSuchArticleException nsae) {
788 return getLatestArticle(groupId, articleId, Boolean.FALSE);
789 }
790 }
791
792 public JournalArticle getArticle(
793 long groupId, String articleId, double version)
794 throws PortalException, SystemException {
795
796 return journalArticlePersistence.findByG_A_V(
797 groupId, articleId, version);
798 }
799
800 public String getArticleContent(
801 long groupId, String articleId, String languageId,
802 ThemeDisplay themeDisplay)
803 throws PortalException, SystemException {
804
805 return getArticleContent(
806 groupId, articleId, null, languageId, themeDisplay);
807 }
808
809 public String getArticleContent(
810 long groupId, String articleId, String templateId,
811 String languageId, ThemeDisplay themeDisplay)
812 throws PortalException, SystemException {
813
814 JournalArticleDisplay articleDisplay = getArticleDisplay(
815 groupId, articleId, templateId, languageId, themeDisplay);
816
817 return articleDisplay.getContent();
818 }
819
820 public String getArticleContent(
821 long groupId, String articleId, double version, String languageId,
822 ThemeDisplay themeDisplay)
823 throws PortalException, SystemException {
824
825 return getArticleContent(
826 groupId, articleId, version, null, languageId, themeDisplay);
827 }
828
829 public String getArticleContent(
830 long groupId, String articleId, double version, String templateId,
831 String languageId, ThemeDisplay themeDisplay)
832 throws PortalException, SystemException {
833
834 JournalArticleDisplay articleDisplay = getArticleDisplay(
835 groupId, articleId, version, templateId, languageId, themeDisplay);
836
837 if (articleDisplay == null) {
838 return StringPool.BLANK;
839 }
840 else {
841 return articleDisplay.getContent();
842 }
843 }
844
845 public JournalArticleDisplay getArticleDisplay(
846 long groupId, String articleId, String languageId,
847 ThemeDisplay themeDisplay)
848 throws PortalException, SystemException {
849
850 return getArticleDisplay(
851 groupId, articleId, null, languageId, themeDisplay);
852 }
853
854 public JournalArticleDisplay getArticleDisplay(
855 long groupId, String articleId, String languageId,
856 int page, String xmlRequest, ThemeDisplay themeDisplay)
857 throws PortalException, SystemException {
858
859 return getArticleDisplay(
860 groupId, articleId, null, languageId, page, xmlRequest,
861 themeDisplay);
862 }
863
864 public JournalArticleDisplay getArticleDisplay(
865 long groupId, String articleId, String templateId,
866 String languageId, ThemeDisplay themeDisplay)
867 throws PortalException, SystemException {
868
869 JournalArticle article = getDisplayArticle(groupId, articleId);
870
871 return getArticleDisplay(
872 groupId, articleId, article.getVersion(), templateId, languageId,
873 themeDisplay);
874 }
875
876 public JournalArticleDisplay getArticleDisplay(
877 long groupId, String articleId, String templateId,
878 String languageId, int page, String xmlRequest,
879 ThemeDisplay themeDisplay)
880 throws PortalException, SystemException {
881
882 JournalArticle article = getDisplayArticle(groupId, articleId);
883
884 return getArticleDisplay(
885 groupId, articleId, article.getVersion(), templateId, languageId,
886 page, xmlRequest, themeDisplay);
887 }
888
889 public JournalArticleDisplay getArticleDisplay(
890 long groupId, String articleId, double version, String templateId,
891 String languageId, ThemeDisplay themeDisplay)
892 throws PortalException, SystemException {
893
894 return getArticleDisplay(
895 groupId, articleId, version, templateId, languageId, 1, null,
896 themeDisplay);
897 }
898
899 public JournalArticleDisplay getArticleDisplay(
900 long groupId, String articleId, double version, String templateId,
901 String languageId, int page, String xmlRequest,
902 ThemeDisplay themeDisplay)
903 throws PortalException, SystemException {
904
905 String content = null;
906
907 Date now = new Date();
908
909 JournalArticle article = journalArticlePersistence.findByG_A_V(
910 groupId, articleId, version);
911
912 if (article.isExpired()) {
913 Date expirationDate = article.getExpirationDate();
914
915 if ((expirationDate != null) && expirationDate.before(now)) {
916 return null;
917 }
918 }
919
920 if (article.getDisplayDate().after(now)) {
921 return null;
922 }
923
924 if (page < 1) {
925 page = 1;
926 }
927
928 int numberOfPages = 1;
929 boolean paginate = false;
930 boolean pageFlow = false;
931
932 boolean cacheable = true;
933
934 Map tokens = JournalUtil.getTokens(groupId, themeDisplay);
935
936 String xml = article.getContent();
937
938 try {
939 Document doc = null;
940
941 Element root = null;
942
943 if (article.isTemplateDriven()) {
944 SAXReader reader = new SAXReader();
945
946 doc = reader.read(new StringReader(xml));
947
948 root = doc.getRootElement();
949
950 Document request = null;
951
952 if (Validator.isNotNull(xmlRequest)) {
953 request = reader.read(new StringReader(xmlRequest));
954 }
955
956 List pages = root.elements("page");
957
958 if (pages.size() > 0) {
959 pageFlow = true;
960
961 String targetPage = request.valueOf(
962 "/request/parameters/parameter[name='targetPage']/" +
963 "value");
964
965 Element pageEl = null;
966
967 if (Validator.isNotNull(targetPage)) {
968 XPath xpathSelector = DocumentHelper.createXPath(
969 "/root/page[@id = '" + targetPage + "']");
970
971 pageEl = (Element)xpathSelector.selectSingleNode(doc);
972 }
973
974 DocumentFactory docFactory = DocumentFactory.getInstance();
975
976 if (pageEl != null) {
977 doc = docFactory.createDocument(pageEl);
978
979 root = doc.getRootElement();
980
981 numberOfPages = pages.size();
982 }
983 else {
984 if (page > pages.size()) {
985 page = 1;
986 }
987
988 pageEl = (Element)pages.get(page - 1);
989
990 doc = docFactory.createDocument(pageEl);
991
992 root = doc.getRootElement();
993
994 numberOfPages = pages.size();
995 paginate = true;
996 }
997 }
998
999 if (request != null) {
1000 root.add(request.getRootElement().createCopy());
1001 }
1002
1003 JournalUtil.addAllReservedEls(root, tokens, article);
1004
1005 xml = JournalUtil.formatXML(doc);
1006 }
1007 }
1008 catch (DocumentException de) {
1009 throw new SystemException(de);
1010 }
1011 catch (IOException ioe) {
1012 throw new SystemException(ioe);
1013 }
1014
1015 try {
1016 if (_log.isDebugEnabled()) {
1017 _log.debug(
1018 "Transforming " + articleId + " " + version + " " +
1019 languageId);
1020 }
1021
1022 String script = null;
1023 String langType = null;
1024
1025 if (article.isTemplateDriven()) {
1026
1027
1032 String defaultTemplateId = article.getTemplateId();
1033
1034 if (Validator.isNull(templateId)) {
1035 templateId = defaultTemplateId;
1036 }
1037
1038 JournalTemplate template = null;
1039
1040 try {
1041 template = journalTemplatePersistence.findByG_T(
1042 groupId, templateId);
1043 }
1044 catch (NoSuchTemplateException nste) {
1045 if (!defaultTemplateId.equals(templateId)) {
1046 template = journalTemplatePersistence.findByG_T(
1047 groupId, defaultTemplateId);
1048 }
1049 else {
1050 throw nste;
1051 }
1052 }
1053
1054 script = template.getXsl();
1055 langType = template.getLangType();
1056 cacheable = template.isCacheable();
1057 }
1058
1059 content = JournalUtil.transform(
1060 tokens, languageId, xml, script, langType);
1061
1062 if (!pageFlow) {
1063 String[] pieces = StringUtil.split(content, _TOKEN_PAGE_BREAK);
1064
1065 if (pieces.length > 1) {
1066 if (page > pieces.length) {
1067 page = 1;
1068 }
1069
1070 content = pieces[page - 1];
1071 numberOfPages = pieces.length;
1072 paginate = true;
1073 }
1074 }
1075 }
1076 catch (Exception e) {
1077 throw new SystemException(e);
1078 }
1079
1080 return new JournalArticleDisplayImpl(
1081 article.getId(), article.getResourcePrimKey(), article.getGroupId(),
1082 article.getUserId(), article.getArticleId(), article.getVersion(),
1083 article.getTitle(), article.getDescription(),
1084 article.getAvailableLocales(), content, article.getType(),
1085 article.getStructureId(), templateId, article.isSmallImage(),
1086 article.getSmallImageId(), article.getSmallImageURL(),
1087 numberOfPages, page, paginate, cacheable);
1088 }
1089
1090 public List getArticles() throws SystemException {
1091 return journalArticlePersistence.findAll();
1092 }
1093
1094 public List getArticles(long groupId) throws SystemException {
1095 return journalArticlePersistence.findByGroupId(groupId);
1096 }
1097
1098 public List getArticles(long groupId, int begin, int end)
1099 throws SystemException {
1100
1101 return journalArticlePersistence.findByGroupId(groupId, begin, end);
1102 }
1103
1104 public List getArticles(
1105 long groupId, int begin, int end, OrderByComparator obc)
1106 throws SystemException {
1107
1108 return journalArticlePersistence.findByGroupId(
1109 groupId, begin, end, obc);
1110 }
1111
1112 public List getArticlesBySmallImageId(long smallImageId)
1113 throws SystemException {
1114
1115 return journalArticlePersistence.findBySmallImageId(smallImageId);
1116 }
1117
1118 public int getArticlesCount(long groupId) throws SystemException {
1119 return journalArticlePersistence.countByGroupId(groupId);
1120 }
1121
1122 public JournalArticle getDisplayArticle(long groupId, String articleId)
1123 throws PortalException, SystemException {
1124
1125 List articles = journalArticlePersistence.findByG_A_A(
1126 groupId, articleId, true);
1127
1128 if (articles.size() == 0) {
1129 throw new NoSuchArticleException();
1130 }
1131
1132 Collections.sort(articles, new ArticleDisplayDateComparator());
1133
1134 Date now = new Date();
1135
1136 for (int i = 0; i < articles.size(); i++) {
1137 JournalArticle article = (JournalArticle)articles.get(i);
1138
1139 if (article.getDisplayDate().before(now)) {
1140 return article;
1141 }
1142 }
1143
1144 return (JournalArticle)articles.get(0);
1145 }
1146
1147 public JournalArticle getLatestArticle(long groupId, String articleId)
1148 throws PortalException, SystemException {
1149
1150 return getLatestArticle(groupId, articleId, null);
1151 }
1152
1153 public JournalArticle getLatestArticle(
1154 long groupId, String articleId, Boolean approved)
1155 throws PortalException, SystemException {
1156
1157 List articles = null;
1158
1159 if (approved == null) {
1160 articles = journalArticlePersistence.findByG_A(
1161 groupId, articleId, 0, 1);
1162 }
1163 else {
1164 articles = journalArticlePersistence.findByG_A_A(
1165 groupId, articleId, approved.booleanValue(), 0, 1);
1166 }
1167
1168 if (articles.size() == 0) {
1169 throw new NoSuchArticleException();
1170 }
1171
1172 return (JournalArticle)articles.get(0);
1173 }
1174
1175 public double getLatestVersion(long groupId, String articleId)
1176 throws PortalException, SystemException {
1177
1178 JournalArticle article = getLatestArticle(groupId, articleId);
1179
1180 return article.getVersion();
1181 }
1182
1183 public double getLatestVersion(
1184 long groupId, String articleId, Boolean approved)
1185 throws PortalException, SystemException {
1186
1187 JournalArticle article = getLatestArticle(groupId, articleId, approved);
1188
1189 return article.getVersion();
1190 }
1191
1192 public List getStructureArticles(long groupId, String structureId)
1193 throws SystemException {
1194
1195 return journalArticlePersistence.findByG_S(groupId, structureId);
1196 }
1197
1198 public List getStructureArticles(
1199 long groupId, String structureId, int begin, int end,
1200 OrderByComparator obc)
1201 throws SystemException {
1202
1203 return journalArticlePersistence.findByG_S(
1204 groupId, structureId, begin, end, obc);
1205 }
1206
1207 public int getStructureArticlesCount(long groupId, String structureId)
1208 throws SystemException {
1209
1210 return journalArticlePersistence.countByG_S(groupId, structureId);
1211 }
1212
1213 public List getTemplateArticles(long groupId, String templateId)
1214 throws SystemException {
1215
1216 return journalArticlePersistence.findByG_T(groupId, templateId);
1217 }
1218
1219 public List getTemplateArticles(
1220 long groupId, String templateId, int begin, int end,
1221 OrderByComparator obc)
1222 throws SystemException {
1223
1224 return journalArticlePersistence.findByG_T(
1225 groupId, templateId, begin, end, obc);
1226 }
1227
1228 public int getTemplateArticlesCount(long groupId, String templateId)
1229 throws SystemException {
1230
1231 return journalArticlePersistence.countByG_T(groupId, templateId);
1232 }
1233
1234 public boolean hasArticle(long groupId, String articleId)
1235 throws SystemException {
1236
1237 try {
1238 getArticle(groupId, articleId);
1239
1240 return true;
1241 }
1242 catch (PortalException pe) {
1243 return false;
1244 }
1245 }
1246
1247 public boolean isLatestVersion(
1248 long groupId, String articleId, double version)
1249 throws PortalException, SystemException {
1250
1251 if (getLatestVersion(groupId, articleId) == version) {
1252 return true;
1253 }
1254 else {
1255 return false;
1256 }
1257 }
1258
1259 public boolean isLatestVersion(
1260 long groupId, String articleId, double version, Boolean active)
1261 throws PortalException, SystemException {
1262
1263 if (getLatestVersion(groupId, articleId, active) == version) {
1264 return true;
1265 }
1266 else {
1267 return false;
1268 }
1269 }
1270
1271 public void reIndex(String[] ids) throws SystemException {
1272 if (LuceneUtil.INDEX_READ_ONLY) {
1273 return;
1274 }
1275
1276 long companyId = GetterUtil.getLong(ids[0]);
1277
1278 IndexWriter writer = null;
1279
1280 try {
1281 writer = LuceneUtil.getWriter(companyId);
1282
1283 Iterator itr = journalArticlePersistence.findByCompanyId(
1284 companyId).iterator();
1285
1286 while (itr.hasNext()) {
1287 JournalArticle article = (JournalArticle)itr.next();
1288
1289 if (article.isApproved() && article.isIndexable()) {
1290 long resourcePrimKey = article.getResourcePrimKey();
1291 long groupId = article.getGroupId();
1292 String articleId = article.getArticleId();
1293 double version = article.getVersion();
1294 String title = article.getTitle();
1295 String description = article.getDescription();
1296 String content = article.getContent();
1297 String type = article.getType();
1298 Date displayDate = article.getDisplayDate();
1299
1300 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
1301 JournalArticle.class.getName(), resourcePrimKey);
1302
1303 try {
1304 org.apache.lucene.document.Document doc =
1305 Indexer.getAddArticleDocument(
1306 companyId, groupId, articleId, version, title,
1307 description, content, type, displayDate,
1308 tagsEntries);
1309
1310 writer.addDocument(doc);
1311 }
1312 catch (Exception e1) {
1313 _log.error("Reindexing " + article.getId(), e1);
1314 }
1315 }
1316 }
1317 }
1318 catch (SystemException se) {
1319 throw se;
1320 }
1321 catch (Exception e2) {
1322 throw new SystemException(e2);
1323 }
1324 finally {
1325 try {
1326 if (writer != null) {
1327 LuceneUtil.write(companyId);
1328 }
1329 }
1330 catch (Exception e) {
1331 _log.error(e);
1332 }
1333 }
1334 }
1335
1336 public JournalArticle removeArticleLocale(
1337 long groupId, String articleId, double version, String languageId)
1338 throws PortalException, SystemException {
1339
1340 JournalArticle article = journalArticlePersistence.findByG_A_V(
1341 groupId, articleId, version);
1342
1343 String content = article.getContent();
1344
1345 if (article.isTemplateDriven()) {
1346 content = JournalUtil.removeArticleLocale(content, languageId);
1347 }
1348 else {
1349 content = LocalizationUtil.removeLocalization(
1350 content, "static-content", languageId);
1351 }
1352
1353 article.setContent(content);
1354
1355 journalArticlePersistence.update(article);
1356
1357 return article;
1358 }
1359
1360 public Hits search(long companyId, long groupId, String keywords)
1361 throws SystemException {
1362
1363 return search(companyId, groupId, keywords, "displayDate");
1364 }
1365
1366 public Hits search(
1367 long companyId, long groupId, String keywords, String sortField)
1368 throws SystemException {
1369
1370 Searcher searcher = null;
1371
1372 try {
1373 HitsImpl hits = new HitsImpl();
1374
1375 BooleanQuery contextQuery = new BooleanQuery();
1376
1377 LuceneUtil.addRequiredTerm(
1378 contextQuery, LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
1379
1380 if (groupId > 0) {
1381 LuceneUtil.addRequiredTerm(
1382 contextQuery, LuceneFields.GROUP_ID, groupId);
1383 }
1384
1385 BooleanQuery searchQuery = new BooleanQuery();
1386
1387 if (Validator.isNotNull(keywords)) {
1388 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
1389 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
1390 LuceneUtil.addTerm(
1391 searchQuery, LuceneFields.DESCRIPTION, keywords);
1392 }
1393
1394 BooleanQuery fullQuery = new BooleanQuery();
1395
1396 fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
1397
1398 if (searchQuery.clauses().size() > 0) {
1399 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1400 }
1401
1402 searcher = LuceneUtil.getSearcher(companyId);
1403
1404 Sort sort = new Sort(new SortField(sortField, true));
1405
1406 try {
1407 hits.recordHits(searcher.search(fullQuery, sort), searcher);
1408 }
1409 catch (RuntimeException re) {
1410
1411
1414 String msg = GetterUtil.getString(re.getMessage());
1415
1416 if (!msg.endsWith("does not appear to be indexed")) {
1417 throw re;
1418 }
1419 }
1420
1421 return hits;
1422 }
1423 catch (Exception e) {
1424 return LuceneUtil.closeSearcher(searcher, keywords, e);
1425 }
1426 }
1427
1428 public List search(
1429 long companyId, long groupId, String keywords, Double version,
1430 String type, String structureId, String templateId,
1431 Date displayDateGT, Date displayDateLT, Boolean approved,
1432 Boolean expired, Date reviewDate, int begin, int end,
1433 OrderByComparator obc)
1434 throws SystemException {
1435
1436 return journalArticleFinder.findByKeywords(
1437 companyId, groupId, keywords, version, type, structureId,
1438 templateId, displayDateGT, displayDateLT, approved, expired,
1439 reviewDate, begin, end, obc);
1440 }
1441
1442 public List search(
1443 long companyId, long groupId, String articleId, Double version,
1444 String title, String description, String content, String type,
1445 String structureId, String templateId, Date displayDateGT,
1446 Date displayDateLT, Boolean approved, Boolean expired,
1447 Date reviewDate, boolean andOperator, int begin, int end,
1448 OrderByComparator obc)
1449 throws SystemException {
1450
1451 return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1452 companyId, groupId, articleId, version, title, description, content,
1453 type, structureId, templateId, displayDateGT, displayDateLT,
1454 approved, expired, reviewDate, andOperator, begin, end, obc);
1455 }
1456
1457 public List search(
1458 long companyId, long groupId, String articleId, Double version,
1459 String title, String description, String content, String type,
1460 String[] structureIds, String[] templateIds, Date displayDateGT,
1461 Date displayDateLT, Boolean approved, Boolean expired,
1462 Date reviewDate, boolean andOperator, int begin, int end,
1463 OrderByComparator obc)
1464 throws SystemException {
1465
1466 return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1467 companyId, groupId, articleId, version, title, description, content,
1468 type, structureIds, templateIds, displayDateGT, displayDateLT,
1469 approved, expired, reviewDate, andOperator, begin, end, obc);
1470 }
1471
1472 public int searchCount(
1473 long companyId, long groupId, String keywords, Double version,
1474 String type, String structureId, String templateId,
1475 Date displayDateGT, Date displayDateLT, Boolean approved,
1476 Boolean expired, Date reviewDate)
1477 throws SystemException {
1478
1479 return journalArticleFinder.countByKeywords(
1480 companyId, groupId, keywords, version, type, structureId,
1481 templateId, displayDateGT, displayDateLT, approved, expired,
1482 reviewDate);
1483 }
1484
1485 public int searchCount(
1486 long companyId, long groupId, String articleId, Double version,
1487 String title, String description, String content, String type,
1488 String structureId, String templateId, Date displayDateGT,
1489 Date displayDateLT, Boolean approved, Boolean expired,
1490 Date reviewDate, boolean andOperator)
1491 throws SystemException {
1492
1493 return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1494 companyId, groupId, articleId, version, title, description, content,
1495 type, structureId, templateId, displayDateGT, displayDateLT,
1496 approved, expired, reviewDate, andOperator);
1497 }
1498
1499 public int searchCount(
1500 long companyId, long groupId, String articleId, Double version,
1501 String title, String description, String content, String type,
1502 String[] structureIds, String[] templateIds, Date displayDateGT,
1503 Date displayDateLT, Boolean approved, Boolean expired,
1504 Date reviewDate, boolean andOperator)
1505 throws SystemException {
1506
1507 return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1508 companyId, groupId, articleId, version, title, description, content,
1509 type, structureIds, templateIds, displayDateGT, displayDateLT,
1510 approved, expired, reviewDate, andOperator);
1511 }
1512
1513 public JournalArticle updateArticle(
1514 long userId, long groupId, String articleId, double version,
1515 boolean incrementVersion, String title, String description,
1516 String content, String type, String structureId, String templateId,
1517 int displayDateMonth, int displayDateDay, int displayDateYear,
1518 int displayDateHour, int displayDateMinute, int expirationDateMonth,
1519 int expirationDateDay, int expirationDateYear,
1520 int expirationDateHour, int expirationDateMinute,
1521 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
1522 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
1523 boolean neverReview, boolean indexable, boolean smallImage,
1524 String smallImageURL, File smallFile, Map images, String articleURL,
1525 PortletPreferences prefs, String[] tagsEntries)
1526 throws PortalException, SystemException {
1527
1528
1530 User user = userPersistence.findByPrimaryKey(userId);
1531 articleId = articleId.trim().toUpperCase();
1532 Date now = new Date();
1533
1534 Date displayDate = PortalUtil.getDate(
1535 displayDateMonth, displayDateDay, displayDateYear,
1536 displayDateHour, displayDateMinute, user.getTimeZone(),
1537 new ArticleDisplayDateException());
1538
1539 Date expirationDate = null;
1540
1541 if (!neverExpire) {
1542 expirationDate = PortalUtil.getDate(
1543 expirationDateMonth, expirationDateDay, expirationDateYear,
1544 expirationDateHour, expirationDateMinute, user.getTimeZone(),
1545 new ArticleExpirationDateException());
1546 }
1547
1548 Date reviewDate = null;
1549
1550 if (!neverReview) {
1551 reviewDate = PortalUtil.getDate(
1552 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1553 reviewDateMinute, user.getTimeZone(),
1554 new ArticleReviewDateException());
1555 }
1556
1557 byte[] smallBytes = null;
1558
1559 try {
1560 smallBytes = FileUtil.getBytes(smallFile);
1561 }
1562 catch (IOException ioe) {
1563 }
1564
1565 validate(
1566 groupId, title, content, type, structureId, templateId, smallImage,
1567 smallImageURL, smallFile, smallBytes);
1568
1569 JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
1570 groupId, articleId, version);
1571
1572 JournalArticle article = null;
1573
1574 if (incrementVersion) {
1575 double latestVersion = getLatestVersion(groupId, articleId);
1576
1577 long id = counterLocalService.increment();
1578
1579 article = journalArticlePersistence.create(id);
1580
1581 article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1582 article.setGroupId(oldArticle.getGroupId());
1583 article.setCompanyId(user.getCompanyId());
1584 article.setUserId(user.getUserId());
1585 article.setUserName(user.getFullName());
1586 article.setCreateDate(now);
1587 article.setArticleId(articleId);
1588 article.setVersion(MathUtil.format(latestVersion + 0.1, 1, 1));
1589 article.setSmallImageId(oldArticle.getSmallImageId());
1590 }
1591 else {
1592 article = oldArticle;
1593 }
1594
1595 content = format(
1596 groupId, articleId, article.getVersion(), incrementVersion, content,
1597 structureId, images);
1598
1599 boolean approved = oldArticle.isApproved();
1600
1601 if (incrementVersion) {
1602 approved = false;
1603 }
1604
1605 article.setModifiedDate(now);
1606 article.setTitle(title);
1607 article.setDescription(description);
1608 article.setContent(content);
1609 article.setType(type);
1610 article.setStructureId(structureId);
1611 article.setTemplateId(templateId);
1612 article.setDisplayDate(displayDate);
1613 article.setApproved(approved);
1614
1615 if ((expirationDate == null) || expirationDate.after(now)) {
1616 article.setExpired(false);
1617 }
1618 else {
1619 article.setExpired(true);
1620 }
1621
1622 article.setExpirationDate(expirationDate);
1623 article.setReviewDate(reviewDate);
1624 article.setIndexable(indexable);
1625 article.setSmallImage(smallImage);
1626
1627 if (article.getSmallImageId() == 0) {
1628 article.setSmallImageId(counterLocalService.increment());
1629 }
1630
1631 article.setSmallImageURL(smallImageURL);
1632
1633 journalArticlePersistence.update(article);
1634
1635
1637 saveImages(
1638 smallImage, article.getSmallImageId(), smallFile, smallBytes);
1639
1640
1642 updateTagsAsset(userId, article, tagsEntries);
1643
1644
1646 if (incrementVersion) {
1647 sendEmail(article, articleURL, prefs, "requested");
1648 }
1649
1650
1652 try {
1653 if (article.isIndexable()) {
1654 if (article.isApproved()) {
1655 Indexer.updateArticle(
1656 article.getCompanyId(), article.getGroupId(),
1657 article.getArticleId(), article.getVersion(),
1658 article.getTitle(), article.getDescription(),
1659 article.getContent(), article.getType(),
1660 article.getDisplayDate(), tagsEntries);
1661 }
1662 else {
1663 Indexer.deleteArticle(
1664 article.getCompanyId(), article.getArticleId());
1665 }
1666 }
1667 }
1668 catch (IOException ioe) {
1669 _log.error("Indexing " + article.getPrimaryKey(), ioe);
1670 }
1671
1672 return article;
1673 }
1674
1675 public JournalArticle updateContent(
1676 long groupId, String articleId, double version, String content)
1677 throws PortalException, SystemException {
1678
1679 JournalArticle article = journalArticlePersistence.findByG_A_V(
1680 groupId, articleId, version);
1681
1682 article.setContent(content);
1683
1684 journalArticlePersistence.update(article);
1685
1686 return article;
1687 }
1688
1689 public void updateTagsAsset(
1690 long userId, JournalArticle article, String[] tagsEntries)
1691 throws PortalException, SystemException {
1692
1693 boolean updateAsset = true;
1694
1695 if (article.getVersion() == 1) {
1696 }
1697 else if (!article.isApproved()) {
1698 updateAsset = false;
1699 }
1700 else if (!isLatestVersion(
1701 article.getGroupId(), article.getArticleId(),
1702 article.getVersion(), Boolean.TRUE)) {
1703
1704 updateAsset = false;
1705 }
1706
1707 if (updateAsset) {
1708 tagsAssetLocalService.updateAsset(
1709 userId, article.getGroupId(), JournalArticle.class.getName(),
1710 article.getResourcePrimKey(), tagsEntries, null, null,
1711 article.getDisplayDate(), article.getExpirationDate(),
1712 ContentTypes.TEXT_HTML, article.getTitle(),
1713 article.getDescription(), null, null, 0, 0, null, false);
1714 }
1715 }
1716
1717 protected void checkStructure(JournalArticle article)
1718 throws DocumentException, PortalException, SystemException {
1719
1720 JournalStructure structure = journalStructurePersistence.findByG_S(
1721 article.getGroupId(), article.getStructureId());
1722
1723 String content = GetterUtil.getString(article.getContent());
1724
1725 SAXReader reader = new SAXReader();
1726
1727 Document contentDoc = reader.read(new StringReader(content));
1728 Document xsdDoc = reader.read(new StringReader(structure.getXsd()));
1729
1730 try {
1731 checkStructure(contentDoc, xsdDoc.getRootElement());
1732 }
1733 catch (StructureXsdException sxsde) {
1734 long groupId = article.getGroupId();
1735 String articleId = article.getArticleId();
1736 double version = article.getVersion();
1737
1738 _log.error(
1739 "Article {groupId=" + groupId + ", articleId=" + articleId +
1740 ", version=" + version +
1741 "} has content that does not match its structure: " +
1742 sxsde.getMessage());
1743 }
1744 }
1745
1746 protected void checkStructure(Document contentDoc, Element root)
1747 throws PortalException {
1748
1749 Iterator itr = root.elements().iterator();
1750
1751 while (itr.hasNext()) {
1752 Element el = (Element)itr.next();
1753
1754 checkStructureField(el, contentDoc);
1755
1756 checkStructure(contentDoc, el);
1757 }
1758 }
1759
1760 protected void checkStructureField(Element el, Document contentDoc)
1761 throws PortalException {
1762
1763 StringMaker elPath = new StringMaker();
1764
1765 elPath.append(el.attributeValue("name"));
1766
1767 Element elParent = (Element)el.getParent();
1768
1769 for (;;) {
1770 if ((elParent == null) ||
1771 (elParent.getName().equals("root"))) {
1772
1773 break;
1774 }
1775
1776 elPath.insert(
1777 0, elParent.attributeValue("name") + StringPool.COMMA);
1778
1779 elParent = (Element)elParent.getParent();
1780 }
1781
1782 String[] elPathNames = StringUtil.split(elPath.toString());
1783
1784 Element contentEl = contentDoc.getRootElement();
1785
1786 for (int i = 0; i < elPathNames.length; i++) {
1787 boolean foundEl = false;
1788
1789 Iterator itr = contentEl.elements().iterator();
1790
1791 while (itr.hasNext()) {
1792 Element tempEl = (Element)itr.next();
1793
1794 if (elPathNames[i].equals(
1795 tempEl.attributeValue("name", StringPool.BLANK))) {
1796
1797 contentEl = tempEl;
1798 foundEl = true;
1799
1800 break;
1801 }
1802 }
1803
1804 if (!foundEl) {
1805 String elType = contentEl.attributeValue(
1806 "type", StringPool.BLANK);
1807
1808 if (!elType.equals("list") && !elType.equals("multi-list")) {
1809 throw new StructureXsdException(elPath.toString());
1810 }
1811
1812 break;
1813 }
1814 }
1815 }
1816
1817 protected String format(
1818 long groupId, String articleId, double version,
1819 boolean incrementVersion, String content, String structureId,
1820 Map images)
1821 throws SystemException {
1822
1823 if (Validator.isNotNull(structureId)) {
1824 SAXReader reader = new SAXReader();
1825
1826 Document doc = null;
1827
1828 try {
1829 doc = reader.read(new StringReader(content));
1830
1831 Element root = doc.getRootElement();
1832
1833 format(
1834 groupId, articleId, version, incrementVersion,
1835 root, images);
1836
1837 content = JournalUtil.formatXML(doc);
1838 }
1839 catch (DocumentException de) {
1840 _log.error(de);
1841 }
1842 catch (IOException ioe) {
1843 _log.error(ioe);
1844 }
1845 }
1846
1847 content = Html.replaceMsWordCharacters(content);
1848
1849 return content;
1850 }
1851
1852 protected void format(
1853 long groupId, String articleId, double version,
1854 boolean incrementVersion, Element root, Map images)
1855 throws SystemException {
1856
1857 Iterator itr = root.elements().iterator();
1858
1859 while (itr.hasNext()) {
1860 Element el = (Element)itr.next();
1861
1862 String elName = el.attributeValue("name", StringPool.BLANK);
1863 String elType = el.attributeValue("type", StringPool.BLANK);
1864
1865 if (elType.equals("image")) {
1866 formatImage(
1867 groupId, articleId, version, incrementVersion, el, elName,
1868 images);
1869 }
1870
1890
1891 format(
1892 groupId, articleId, version, incrementVersion, el, images);
1893 }
1894 }
1895
1896 protected void formatImage(
1897 long groupId, String articleId, double version,
1898 boolean incrementVersion, Element el, String elName, Map images)
1899 throws SystemException {
1900
1901 List imageContents = el.elements("dynamic-content");
1902
1903 Iterator itr = imageContents.listIterator();
1904
1905 while (itr.hasNext()) {
1906 Element dynamicContent = (Element)itr.next();
1907
1908 String elLanguage = dynamicContent.attributeValue(
1909 "language-id", StringPool.BLANK);
1910
1911 if (!elLanguage.equals(StringPool.BLANK)) {
1912 elLanguage = "_" + elLanguage;
1913 }
1914
1915 long imageId =
1916 journalArticleImageLocalService.getArticleImageId(
1917 groupId, articleId, version, elName, elLanguage);
1918
1919 double oldVersion = MathUtil.format(version - 0.1, 1, 1);
1920
1921 long oldImageId = 0;
1922
1923 if (oldVersion >= 1) {
1924 oldImageId =
1925 journalArticleImageLocalService.getArticleImageId(
1926 groupId, articleId, oldVersion, elName, elLanguage);
1927 }
1928
1929 String elContent =
1930 "/image/journal/article?img_id=" + imageId + "&t=" +
1931 ImageServletTokenUtil.getToken(imageId);
1932
1933 if (dynamicContent.getText().equals("delete")) {
1934 dynamicContent.setText(StringPool.BLANK);
1935
1936 ImageLocalUtil.deleteImage(imageId);
1937
1938 String defaultElLanguage = "";
1939
1940 if (!Validator.isNotNull(elLanguage)) {
1941 defaultElLanguage =
1942 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
1943 }
1944
1945 long defaultImageId =
1946 journalArticleImageLocalService.getArticleImageId(
1947 groupId, articleId, version, elName, defaultElLanguage);
1948
1949 ImageLocalUtil.deleteImage(defaultImageId);
1950
1951 continue;
1952 }
1953
1954 byte[] bytes = (byte[])images.get(elName + elLanguage);
1955
1956 if (bytes != null && (bytes.length > 0)) {
1957 dynamicContent.setText(elContent);
1958 dynamicContent.addAttribute("id", String.valueOf(imageId));
1959
1960 ImageLocalUtil.updateImage(imageId, bytes);
1961
1962 continue;
1963 }
1964
1965 if ((version > JournalArticleImpl.DEFAULT_VERSION) &&
1966 (incrementVersion)) {
1967
1968 Image oldImage = null;
1969
1970 if (oldImageId > 0) {
1971 oldImage = ImageLocalUtil.getImage(oldImageId);
1972 }
1973
1974 if (oldImage != null) {
1975 dynamicContent.setText(elContent);
1976 dynamicContent.addAttribute("id", String.valueOf(imageId));
1977
1978 bytes = oldImage.getTextObj();
1979
1980 ImageLocalUtil.updateImage(imageId, bytes);
1981 }
1982
1983 continue;
1984 }
1985
1986 Image image = ImageLocalUtil.getImage(imageId);
1987
1988 if (image != null) {
1989 dynamicContent.setText(elContent);
1990 dynamicContent.addAttribute("id", String.valueOf(imageId));
1991
1992 continue;
1993 }
1994
1995 String defaultElLanguage = "";
1996
1997 if (!Validator.isNotNull(elLanguage)) {
1998 defaultElLanguage =
1999 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2000 }
2001
2002 long defaultImageId =
2003 journalArticleImageLocalService.getArticleImageId(
2004 groupId, articleId, version, elName, defaultElLanguage);
2005
2006 Image defaultImage = ImageLocalUtil.getImage(defaultImageId);
2007
2008 if (defaultImage != null) {
2009 dynamicContent.setText(elContent);
2010 dynamicContent.addAttribute("id", String.valueOf(imageId));
2011
2012 bytes = defaultImage.getTextObj();
2013
2014 ImageLocalUtil.updateImage(imageId, bytes);
2015
2016 continue;
2017 }
2018
2019 dynamicContent.setText(StringPool.BLANK);
2020 }
2021 }
2022
2023 protected void saveImages(
2024 boolean smallImage, long smallImageId, File smallFile,
2025 byte[] smallBytes)
2026 throws SystemException {
2027
2028 if (smallImage) {
2029 if ((smallFile != null) && (smallBytes != null)) {
2030 ImageLocalUtil.updateImage(smallImageId, smallBytes);
2031 }
2032 }
2033 else {
2034 ImageLocalUtil.deleteImage(smallImageId);
2035 }
2036 }
2037
2038 protected void sendEmail(
2039 JournalArticle article, String articleURL, PortletPreferences prefs,
2040 String emailType)
2041 throws PortalException, SystemException {
2042
2043 try {
2044 if (prefs == null) {
2045 return;
2046 }
2047 else if (emailType.equals("denied") &&
2048 JournalUtil.getEmailArticleApprovalDeniedEnabled(prefs)) {
2049 }
2050 else if (emailType.equals("granted") &&
2051 JournalUtil.getEmailArticleApprovalGrantedEnabled(prefs)) {
2052 }
2053 else if (emailType.equals("requested") &&
2054 JournalUtil.getEmailArticleApprovalRequestedEnabled(
2055 prefs)) {
2056 }
2057 else if (emailType.equals("review") &&
2058 JournalUtil.getEmailArticleReviewEnabled(prefs)) {
2059 }
2060 else {
2061 return;
2062 }
2063
2064 Company company = companyPersistence.findByPrimaryKey(
2065 article.getCompanyId());
2066
2067 User user = userPersistence.findByPrimaryKey(article.getUserId());
2068
2069 articleURL +=
2070 "&groupId=" + article.getGroupId() + "&articleId=" +
2071 article.getArticleId() + "&version=" + article.getVersion();
2072
2073 String portletName = PortalUtil.getPortletTitle(
2074 PortletKeys.JOURNAL, user);
2075
2076 String fromName = JournalUtil.getEmailFromName(prefs);
2077 String fromAddress = JournalUtil.getEmailFromAddress(prefs);
2078
2079 String toName = user.getFullName();
2080 String toAddress = user.getEmailAddress();
2081
2082 if (emailType.equals("requested") ||
2083 emailType.equals("review")) {
2084
2085 String tempToName = fromName;
2086 String tempToAddress = fromAddress;
2087
2088 fromName = toName;
2089 fromAddress = toAddress;
2090
2091 toName = tempToName;
2092 toAddress = tempToAddress;
2093 }
2094
2095 String subject = null;
2096 String body = null;
2097
2098 if (emailType.equals("denied")) {
2099 subject =
2100 JournalUtil.getEmailArticleApprovalDeniedSubject(prefs);
2101 body = JournalUtil.getEmailArticleApprovalDeniedBody(prefs);
2102 }
2103 else if (emailType.equals("granted")) {
2104 subject =
2105 JournalUtil.getEmailArticleApprovalGrantedSubject(prefs);
2106 body = JournalUtil.getEmailArticleApprovalGrantedBody(prefs);
2107 }
2108 else if (emailType.equals("requested")) {
2109 subject =
2110 JournalUtil.getEmailArticleApprovalRequestedSubject(prefs);
2111 body = JournalUtil.getEmailArticleApprovalRequestedBody(prefs);
2112 }
2113 else if (emailType.equals("review")) {
2114 subject = JournalUtil.getEmailArticleReviewSubject(prefs);
2115 body = JournalUtil.getEmailArticleReviewBody(prefs);
2116 }
2117
2118 subject = StringUtil.replace(
2119 subject,
2120 new String[] {
2121 "[$ARTICLE_ID$]",
2122 "[$ARTICLE_TITLE$]",
2123 "[$ARTICLE_URL$]",
2124 "[$ARTICLE_VERSION$]",
2125 "[$FROM_ADDRESS$]",
2126 "[$FROM_NAME$]",
2127 "[$PORTAL_URL$]",
2128 "[$PORTLET_NAME$]",
2129 "[$TO_ADDRESS$]",
2130 "[$TO_NAME$]"
2131 },
2132 new String[] {
2133 article.getArticleId(),
2134 article.getTitle(),
2135 articleURL,
2136 String.valueOf(article.getVersion()),
2137 fromAddress,
2138 fromName,
2139 company.getVirtualHost(),
2140 portletName,
2141 toAddress,
2142 toName,
2143 });
2144
2145 body = StringUtil.replace(
2146 body,
2147 new String[] {
2148 "[$ARTICLE_ID$]",
2149 "[$ARTICLE_TITLE$]",
2150 "[$ARTICLE_URL$]",
2151 "[$ARTICLE_VERSION$]",
2152 "[$FROM_ADDRESS$]",
2153 "[$FROM_NAME$]",
2154 "[$PORTAL_URL$]",
2155 "[$PORTLET_NAME$]",
2156 "[$TO_ADDRESS$]",
2157 "[$TO_NAME$]"
2158 },
2159 new String[] {
2160 article.getArticleId(),
2161 article.getTitle(),
2162 articleURL,
2163 String.valueOf(article.getVersion()),
2164 fromAddress,
2165 fromName,
2166 company.getVirtualHost(),
2167 portletName,
2168 toAddress,
2169 toName,
2170 });
2171
2172 InternetAddress from = new InternetAddress(fromAddress, fromName);
2173
2174 InternetAddress to = new InternetAddress(toAddress, toName);
2175
2176 MailMessage message = new MailMessage(
2177 from, to, subject, body, true);
2178
2179 mailService.sendEmail(message);
2180 }
2181 catch (IOException ioe) {
2182 throw new SystemException(ioe);
2183 }
2184 catch (PortalException pe) {
2185 throw pe;
2186 }
2187 }
2188
2189 protected void validate(
2190 long groupId, String articleId, boolean autoArticleId, String title,
2191 String content, String type, String structureId, String templateId,
2192 boolean smallImage, String smallImageURL, File smallFile,
2193 byte[] smallBytes)
2194 throws PortalException, SystemException {
2195
2196 if (!autoArticleId) {
2197 if ((Validator.isNull(articleId)) ||
2198 (Validator.isNumber(articleId)) ||
2199 (articleId.indexOf(StringPool.SPACE) != -1)) {
2200
2201 throw new ArticleIdException();
2202 }
2203
2204 try {
2205 journalArticlePersistence.findByG_A_V(
2206 groupId, articleId, JournalArticleImpl.DEFAULT_VERSION);
2207
2208 throw new DuplicateArticleIdException();
2209 }
2210 catch (NoSuchArticleException nste) {
2211 }
2212 }
2213
2214 validate(
2215 groupId, title, content, type, structureId, templateId,
2216 smallImage, smallImageURL, smallFile, smallBytes);
2217 }
2218
2219 protected void validate(
2220 long groupId, String title, String content, String type,
2221 String structureId, String templateId, boolean smallImage,
2222 String smallImageURL, File smallFile, byte[] smallBytes)
2223 throws PortalException, SystemException {
2224
2225 if (Validator.isNull(title)) {
2226 throw new ArticleTitleException();
2227 }
2228 else if (Validator.isNull(content)) {
2229 throw new ArticleContentException();
2230 }
2231 else if (Validator.isNull(type)) {
2232 throw new ArticleTypeException();
2233 }
2234
2235 if (Validator.isNotNull(structureId)) {
2236 journalStructurePersistence.findByG_S(groupId, structureId);
2237
2238 JournalTemplate template = journalTemplatePersistence.findByG_T(
2239 groupId, templateId);
2240
2241 if (!template.getStructureId().equals(structureId)) {
2242 throw new NoSuchTemplateException();
2243 }
2244 }
2245
2246 String[] imageExtensions =
2247 PropsUtil.getArray(PropsUtil.JOURNAL_IMAGE_EXTENSIONS);
2248
2249 if (smallImage && Validator.isNull(smallImageURL) &&
2250 smallFile != null && smallBytes != null) {
2251
2252 String smallImageName = smallFile.getName();
2253
2254 if (smallImageName != null) {
2255 boolean validSmallImageExtension = false;
2256
2257 for (int i = 0; i < imageExtensions.length; i++) {
2258 if (StringPool.STAR.equals(imageExtensions[i]) ||
2259 StringUtil.endsWith(
2260 smallImageName, imageExtensions[i])) {
2261
2262 validSmallImageExtension = true;
2263
2264 break;
2265 }
2266 }
2267
2268 if (!validSmallImageExtension) {
2269 throw new ArticleSmallImageNameException(smallImageName);
2270 }
2271 }
2272
2273 long smallImageMaxSize = GetterUtil.getLong(
2274 PropsUtil.get(PropsUtil.JOURNAL_IMAGE_SMALL_MAX_SIZE));
2275
2276 if ((smallImageMaxSize > 0) &&
2277 ((smallBytes == null) ||
2278 (smallBytes.length > smallImageMaxSize))) {
2279
2280 throw new ArticleSmallImageSizeException();
2281 }
2282 }
2283 }
2284
2285 private static final String _TOKEN_PAGE_BREAK = PropsUtil.get(
2286 PropsUtil.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
2287
2288 private static Log _log =
2289 LogFactory.getLog(JournalArticleLocalServiceImpl.class);
2290
2291}