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 tokens.put(
937 "article_resource_pk",
938 String.valueOf(article.getResourcePrimKey()));
939
940 String xml = article.getContent();
941
942 try {
943 Document doc = null;
944
945 Element root = null;
946
947 if (article.isTemplateDriven()) {
948 SAXReader reader = new SAXReader();
949
950 doc = reader.read(new StringReader(xml));
951
952 root = doc.getRootElement();
953
954 Document request = null;
955
956 if (Validator.isNotNull(xmlRequest)) {
957 request = reader.read(new StringReader(xmlRequest));
958 }
959
960 List pages = root.elements("page");
961
962 if (pages.size() > 0) {
963 pageFlow = true;
964
965 String targetPage = request.valueOf(
966 "/request/parameters/parameter[name='targetPage']/" +
967 "value");
968
969 Element pageEl = null;
970
971 if (Validator.isNotNull(targetPage)) {
972 XPath xpathSelector = DocumentHelper.createXPath(
973 "/root/page[@id = '" + targetPage + "']");
974
975 pageEl = (Element)xpathSelector.selectSingleNode(doc);
976 }
977
978 DocumentFactory docFactory = DocumentFactory.getInstance();
979
980 if (pageEl != null) {
981 doc = docFactory.createDocument(pageEl);
982
983 root = doc.getRootElement();
984
985 numberOfPages = pages.size();
986 }
987 else {
988 if (page > pages.size()) {
989 page = 1;
990 }
991
992 pageEl = (Element)pages.get(page - 1);
993
994 doc = docFactory.createDocument(pageEl);
995
996 root = doc.getRootElement();
997
998 numberOfPages = pages.size();
999 paginate = true;
1000 }
1001 }
1002
1003 if (request != null) {
1004 root.add(request.getRootElement().createCopy());
1005 }
1006
1007 JournalUtil.addAllReservedEls(root, tokens, article);
1008
1009 xml = JournalUtil.formatXML(doc);
1010 }
1011 }
1012 catch (DocumentException de) {
1013 throw new SystemException(de);
1014 }
1015 catch (IOException ioe) {
1016 throw new SystemException(ioe);
1017 }
1018
1019 try {
1020 if (_log.isDebugEnabled()) {
1021 _log.debug(
1022 "Transforming " + articleId + " " + version + " " +
1023 languageId);
1024 }
1025
1026 String script = null;
1027 String langType = null;
1028
1029 if (article.isTemplateDriven()) {
1030
1031
1036 String defaultTemplateId = article.getTemplateId();
1037
1038 if (Validator.isNull(templateId)) {
1039 templateId = defaultTemplateId;
1040 }
1041
1042 JournalTemplate template = null;
1043
1044 try {
1045 template = journalTemplatePersistence.findByG_T(
1046 groupId, templateId);
1047 }
1048 catch (NoSuchTemplateException nste) {
1049 if (!defaultTemplateId.equals(templateId)) {
1050 template = journalTemplatePersistence.findByG_T(
1051 groupId, defaultTemplateId);
1052 }
1053 else {
1054 throw nste;
1055 }
1056 }
1057
1058 script = template.getXsl();
1059 langType = template.getLangType();
1060 cacheable = template.isCacheable();
1061 }
1062
1063 content = JournalUtil.transform(
1064 tokens, languageId, xml, script, langType);
1065
1066 if (!pageFlow) {
1067 String[] pieces = StringUtil.split(content, _TOKEN_PAGE_BREAK);
1068
1069 if (pieces.length > 1) {
1070 if (page > pieces.length) {
1071 page = 1;
1072 }
1073
1074 content = pieces[page - 1];
1075 numberOfPages = pieces.length;
1076 paginate = true;
1077 }
1078 }
1079 }
1080 catch (Exception e) {
1081 throw new SystemException(e);
1082 }
1083
1084 return new JournalArticleDisplayImpl(
1085 article.getId(), article.getResourcePrimKey(), article.getGroupId(),
1086 article.getUserId(), article.getArticleId(), article.getVersion(),
1087 article.getTitle(), article.getDescription(),
1088 article.getAvailableLocales(), content, article.getType(),
1089 article.getStructureId(), templateId, article.isSmallImage(),
1090 article.getSmallImageId(), article.getSmallImageURL(),
1091 numberOfPages, page, paginate, cacheable);
1092 }
1093
1094 public List getArticles() throws SystemException {
1095 return journalArticlePersistence.findAll();
1096 }
1097
1098 public List getArticles(long groupId) throws SystemException {
1099 return journalArticlePersistence.findByGroupId(groupId);
1100 }
1101
1102 public List getArticles(long groupId, int begin, int end)
1103 throws SystemException {
1104
1105 return journalArticlePersistence.findByGroupId(groupId, begin, end);
1106 }
1107
1108 public List getArticles(
1109 long groupId, int begin, int end, OrderByComparator obc)
1110 throws SystemException {
1111
1112 return journalArticlePersistence.findByGroupId(
1113 groupId, begin, end, obc);
1114 }
1115
1116 public List getArticlesBySmallImageId(long smallImageId)
1117 throws SystemException {
1118
1119 return journalArticlePersistence.findBySmallImageId(smallImageId);
1120 }
1121
1122 public int getArticlesCount(long groupId) throws SystemException {
1123 return journalArticlePersistence.countByGroupId(groupId);
1124 }
1125
1126 public JournalArticle getDisplayArticle(long groupId, String articleId)
1127 throws PortalException, SystemException {
1128
1129 List articles = journalArticlePersistence.findByG_A_A(
1130 groupId, articleId, true);
1131
1132 if (articles.size() == 0) {
1133 throw new NoSuchArticleException();
1134 }
1135
1136 Collections.sort(articles, new ArticleDisplayDateComparator());
1137
1138 Date now = new Date();
1139
1140 for (int i = 0; i < articles.size(); i++) {
1141 JournalArticle article = (JournalArticle)articles.get(i);
1142
1143 if (article.getDisplayDate().before(now)) {
1144 return article;
1145 }
1146 }
1147
1148 return (JournalArticle)articles.get(0);
1149 }
1150
1151 public JournalArticle getLatestArticle(long groupId, String articleId)
1152 throws PortalException, SystemException {
1153
1154 return getLatestArticle(groupId, articleId, null);
1155 }
1156
1157 public JournalArticle getLatestArticle(
1158 long groupId, String articleId, Boolean approved)
1159 throws PortalException, SystemException {
1160
1161 List articles = null;
1162
1163 if (approved == null) {
1164 articles = journalArticlePersistence.findByG_A(
1165 groupId, articleId, 0, 1);
1166 }
1167 else {
1168 articles = journalArticlePersistence.findByG_A_A(
1169 groupId, articleId, approved.booleanValue(), 0, 1);
1170 }
1171
1172 if (articles.size() == 0) {
1173 throw new NoSuchArticleException();
1174 }
1175
1176 return (JournalArticle)articles.get(0);
1177 }
1178
1179 public double getLatestVersion(long groupId, String articleId)
1180 throws PortalException, SystemException {
1181
1182 JournalArticle article = getLatestArticle(groupId, articleId);
1183
1184 return article.getVersion();
1185 }
1186
1187 public double getLatestVersion(
1188 long groupId, String articleId, Boolean approved)
1189 throws PortalException, SystemException {
1190
1191 JournalArticle article = getLatestArticle(groupId, articleId, approved);
1192
1193 return article.getVersion();
1194 }
1195
1196 public List getStructureArticles(long groupId, String structureId)
1197 throws SystemException {
1198
1199 return journalArticlePersistence.findByG_S(groupId, structureId);
1200 }
1201
1202 public List getStructureArticles(
1203 long groupId, String structureId, int begin, int end,
1204 OrderByComparator obc)
1205 throws SystemException {
1206
1207 return journalArticlePersistence.findByG_S(
1208 groupId, structureId, begin, end, obc);
1209 }
1210
1211 public int getStructureArticlesCount(long groupId, String structureId)
1212 throws SystemException {
1213
1214 return journalArticlePersistence.countByG_S(groupId, structureId);
1215 }
1216
1217 public List getTemplateArticles(long groupId, String templateId)
1218 throws SystemException {
1219
1220 return journalArticlePersistence.findByG_T(groupId, templateId);
1221 }
1222
1223 public List getTemplateArticles(
1224 long groupId, String templateId, int begin, int end,
1225 OrderByComparator obc)
1226 throws SystemException {
1227
1228 return journalArticlePersistence.findByG_T(
1229 groupId, templateId, begin, end, obc);
1230 }
1231
1232 public int getTemplateArticlesCount(long groupId, String templateId)
1233 throws SystemException {
1234
1235 return journalArticlePersistence.countByG_T(groupId, templateId);
1236 }
1237
1238 public boolean hasArticle(long groupId, String articleId)
1239 throws SystemException {
1240
1241 try {
1242 getArticle(groupId, articleId);
1243
1244 return true;
1245 }
1246 catch (PortalException pe) {
1247 return false;
1248 }
1249 }
1250
1251 public boolean isLatestVersion(
1252 long groupId, String articleId, double version)
1253 throws PortalException, SystemException {
1254
1255 if (getLatestVersion(groupId, articleId) == version) {
1256 return true;
1257 }
1258 else {
1259 return false;
1260 }
1261 }
1262
1263 public boolean isLatestVersion(
1264 long groupId, String articleId, double version, Boolean active)
1265 throws PortalException, SystemException {
1266
1267 if (getLatestVersion(groupId, articleId, active) == version) {
1268 return true;
1269 }
1270 else {
1271 return false;
1272 }
1273 }
1274
1275 public void reIndex(String[] ids) throws SystemException {
1276 if (LuceneUtil.INDEX_READ_ONLY) {
1277 return;
1278 }
1279
1280 long companyId = GetterUtil.getLong(ids[0]);
1281
1282 IndexWriter writer = null;
1283
1284 try {
1285 writer = LuceneUtil.getWriter(companyId);
1286
1287 Iterator itr = journalArticlePersistence.findByCompanyId(
1288 companyId).iterator();
1289
1290 while (itr.hasNext()) {
1291 JournalArticle article = (JournalArticle)itr.next();
1292
1293 if (article.isApproved() && article.isIndexable()) {
1294 long resourcePrimKey = article.getResourcePrimKey();
1295 long groupId = article.getGroupId();
1296 String articleId = article.getArticleId();
1297 double version = article.getVersion();
1298 String title = article.getTitle();
1299 String description = article.getDescription();
1300 String content = article.getContent();
1301 String type = article.getType();
1302 Date displayDate = article.getDisplayDate();
1303
1304 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
1305 JournalArticle.class.getName(), resourcePrimKey);
1306
1307 try {
1308 org.apache.lucene.document.Document doc =
1309 Indexer.getAddArticleDocument(
1310 companyId, groupId, articleId, version, title,
1311 description, content, type, displayDate,
1312 tagsEntries);
1313
1314 writer.addDocument(doc);
1315 }
1316 catch (Exception e1) {
1317 _log.error("Reindexing " + article.getId(), e1);
1318 }
1319 }
1320 }
1321 }
1322 catch (SystemException se) {
1323 throw se;
1324 }
1325 catch (Exception e2) {
1326 throw new SystemException(e2);
1327 }
1328 finally {
1329 try {
1330 if (writer != null) {
1331 LuceneUtil.write(companyId);
1332 }
1333 }
1334 catch (Exception e) {
1335 _log.error(e);
1336 }
1337 }
1338 }
1339
1340 public JournalArticle removeArticleLocale(
1341 long groupId, String articleId, double version, String languageId)
1342 throws PortalException, SystemException {
1343
1344 JournalArticle article = journalArticlePersistence.findByG_A_V(
1345 groupId, articleId, version);
1346
1347 String content = article.getContent();
1348
1349 if (article.isTemplateDriven()) {
1350 content = JournalUtil.removeArticleLocale(content, languageId);
1351 }
1352 else {
1353 content = LocalizationUtil.removeLocalization(
1354 content, "static-content", languageId);
1355 }
1356
1357 article.setContent(content);
1358
1359 journalArticlePersistence.update(article);
1360
1361 return article;
1362 }
1363
1364 public Hits search(long companyId, long groupId, String keywords)
1365 throws SystemException {
1366
1367 return search(companyId, groupId, keywords, "displayDate");
1368 }
1369
1370 public Hits search(
1371 long companyId, long groupId, String keywords, String sortField)
1372 throws SystemException {
1373
1374 Searcher searcher = null;
1375
1376 try {
1377 HitsImpl hits = new HitsImpl();
1378
1379 BooleanQuery contextQuery = new BooleanQuery();
1380
1381 LuceneUtil.addRequiredTerm(
1382 contextQuery, LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
1383
1384 if (groupId > 0) {
1385 LuceneUtil.addRequiredTerm(
1386 contextQuery, LuceneFields.GROUP_ID, groupId);
1387 }
1388
1389 BooleanQuery searchQuery = new BooleanQuery();
1390
1391 if (Validator.isNotNull(keywords)) {
1392 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
1393 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
1394 LuceneUtil.addTerm(
1395 searchQuery, LuceneFields.DESCRIPTION, keywords);
1396 }
1397
1398 BooleanQuery fullQuery = new BooleanQuery();
1399
1400 fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
1401
1402 if (searchQuery.clauses().size() > 0) {
1403 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
1404 }
1405
1406 searcher = LuceneUtil.getSearcher(companyId);
1407
1408 Sort sort = new Sort(new SortField(sortField, true));
1409
1410 try {
1411 hits.recordHits(searcher.search(fullQuery, sort), searcher);
1412 }
1413 catch (RuntimeException re) {
1414
1415
1418 String msg = GetterUtil.getString(re.getMessage());
1419
1420 if (!msg.endsWith("does not appear to be indexed")) {
1421 throw re;
1422 }
1423 }
1424
1425 return hits;
1426 }
1427 catch (Exception e) {
1428 return LuceneUtil.closeSearcher(searcher, keywords, e);
1429 }
1430 }
1431
1432 public List search(
1433 long companyId, long groupId, String keywords, Double version,
1434 String type, String structureId, String templateId,
1435 Date displayDateGT, Date displayDateLT, Boolean approved,
1436 Boolean expired, Date reviewDate, int begin, int end,
1437 OrderByComparator obc)
1438 throws SystemException {
1439
1440 return journalArticleFinder.findByKeywords(
1441 companyId, groupId, keywords, version, type, structureId,
1442 templateId, displayDateGT, displayDateLT, approved, expired,
1443 reviewDate, begin, end, obc);
1444 }
1445
1446 public List search(
1447 long companyId, long groupId, String articleId, Double version,
1448 String title, String description, String content, String type,
1449 String structureId, String templateId, Date displayDateGT,
1450 Date displayDateLT, Boolean approved, Boolean expired,
1451 Date reviewDate, boolean andOperator, int begin, int end,
1452 OrderByComparator obc)
1453 throws SystemException {
1454
1455 return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1456 companyId, groupId, articleId, version, title, description, content,
1457 type, structureId, templateId, displayDateGT, displayDateLT,
1458 approved, expired, reviewDate, andOperator, begin, end, obc);
1459 }
1460
1461 public List search(
1462 long companyId, long groupId, String articleId, Double version,
1463 String title, String description, String content, String type,
1464 String[] structureIds, String[] templateIds, Date displayDateGT,
1465 Date displayDateLT, Boolean approved, Boolean expired,
1466 Date reviewDate, boolean andOperator, int begin, int end,
1467 OrderByComparator obc)
1468 throws SystemException {
1469
1470 return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1471 companyId, groupId, articleId, version, title, description, content,
1472 type, structureIds, templateIds, displayDateGT, displayDateLT,
1473 approved, expired, reviewDate, andOperator, begin, end, obc);
1474 }
1475
1476 public int searchCount(
1477 long companyId, long groupId, String keywords, Double version,
1478 String type, String structureId, String templateId,
1479 Date displayDateGT, Date displayDateLT, Boolean approved,
1480 Boolean expired, Date reviewDate)
1481 throws SystemException {
1482
1483 return journalArticleFinder.countByKeywords(
1484 companyId, groupId, keywords, version, type, structureId,
1485 templateId, displayDateGT, displayDateLT, approved, expired,
1486 reviewDate);
1487 }
1488
1489 public int searchCount(
1490 long companyId, long groupId, String articleId, Double version,
1491 String title, String description, String content, String type,
1492 String structureId, String templateId, Date displayDateGT,
1493 Date displayDateLT, Boolean approved, Boolean expired,
1494 Date reviewDate, boolean andOperator)
1495 throws SystemException {
1496
1497 return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1498 companyId, groupId, articleId, version, title, description, content,
1499 type, structureId, templateId, displayDateGT, displayDateLT,
1500 approved, expired, reviewDate, andOperator);
1501 }
1502
1503 public int searchCount(
1504 long companyId, long groupId, String articleId, Double version,
1505 String title, String description, String content, String type,
1506 String[] structureIds, String[] templateIds, Date displayDateGT,
1507 Date displayDateLT, Boolean approved, Boolean expired,
1508 Date reviewDate, boolean andOperator)
1509 throws SystemException {
1510
1511 return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1512 companyId, groupId, articleId, version, title, description, content,
1513 type, structureIds, templateIds, displayDateGT, displayDateLT,
1514 approved, expired, reviewDate, andOperator);
1515 }
1516
1517 public JournalArticle updateArticle(
1518 long userId, long groupId, String articleId, double version,
1519 boolean incrementVersion, String title, String description,
1520 String content, String type, String structureId, String templateId,
1521 int displayDateMonth, int displayDateDay, int displayDateYear,
1522 int displayDateHour, int displayDateMinute, int expirationDateMonth,
1523 int expirationDateDay, int expirationDateYear,
1524 int expirationDateHour, int expirationDateMinute,
1525 boolean neverExpire, int reviewDateMonth, int reviewDateDay,
1526 int reviewDateYear, int reviewDateHour, int reviewDateMinute,
1527 boolean neverReview, boolean indexable, boolean smallImage,
1528 String smallImageURL, File smallFile, Map images, String articleURL,
1529 PortletPreferences prefs, String[] tagsEntries)
1530 throws PortalException, SystemException {
1531
1532
1534 User user = userPersistence.findByPrimaryKey(userId);
1535 articleId = articleId.trim().toUpperCase();
1536 Date now = new Date();
1537
1538 Date displayDate = PortalUtil.getDate(
1539 displayDateMonth, displayDateDay, displayDateYear,
1540 displayDateHour, displayDateMinute, user.getTimeZone(),
1541 new ArticleDisplayDateException());
1542
1543 Date expirationDate = null;
1544
1545 if (!neverExpire) {
1546 expirationDate = PortalUtil.getDate(
1547 expirationDateMonth, expirationDateDay, expirationDateYear,
1548 expirationDateHour, expirationDateMinute, user.getTimeZone(),
1549 new ArticleExpirationDateException());
1550 }
1551
1552 Date reviewDate = null;
1553
1554 if (!neverReview) {
1555 reviewDate = PortalUtil.getDate(
1556 reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1557 reviewDateMinute, user.getTimeZone(),
1558 new ArticleReviewDateException());
1559 }
1560
1561 byte[] smallBytes = null;
1562
1563 try {
1564 smallBytes = FileUtil.getBytes(smallFile);
1565 }
1566 catch (IOException ioe) {
1567 }
1568
1569 validate(
1570 groupId, title, content, type, structureId, templateId, smallImage,
1571 smallImageURL, smallFile, smallBytes);
1572
1573 JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
1574 groupId, articleId, version);
1575
1576 JournalArticle article = null;
1577
1578 if (incrementVersion) {
1579 double latestVersion = getLatestVersion(groupId, articleId);
1580
1581 long id = counterLocalService.increment();
1582
1583 article = journalArticlePersistence.create(id);
1584
1585 article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1586 article.setGroupId(oldArticle.getGroupId());
1587 article.setCompanyId(user.getCompanyId());
1588 article.setUserId(user.getUserId());
1589 article.setUserName(user.getFullName());
1590 article.setCreateDate(now);
1591 article.setArticleId(articleId);
1592 article.setVersion(MathUtil.format(latestVersion + 0.1, 1, 1));
1593 article.setSmallImageId(oldArticle.getSmallImageId());
1594 }
1595 else {
1596 article = oldArticle;
1597 }
1598
1599 content = format(
1600 groupId, articleId, article.getVersion(), incrementVersion, content,
1601 structureId, images);
1602
1603 boolean approved = oldArticle.isApproved();
1604
1605 if (incrementVersion) {
1606 approved = false;
1607 }
1608
1609 article.setModifiedDate(now);
1610 article.setTitle(title);
1611 article.setDescription(description);
1612 article.setContent(content);
1613 article.setType(type);
1614 article.setStructureId(structureId);
1615 article.setTemplateId(templateId);
1616 article.setDisplayDate(displayDate);
1617 article.setApproved(approved);
1618
1619 if ((expirationDate == null) || expirationDate.after(now)) {
1620 article.setExpired(false);
1621 }
1622 else {
1623 article.setExpired(true);
1624 }
1625
1626 article.setExpirationDate(expirationDate);
1627 article.setReviewDate(reviewDate);
1628 article.setIndexable(indexable);
1629 article.setSmallImage(smallImage);
1630
1631 if (article.getSmallImageId() == 0) {
1632 article.setSmallImageId(counterLocalService.increment());
1633 }
1634
1635 article.setSmallImageURL(smallImageURL);
1636
1637 journalArticlePersistence.update(article);
1638
1639
1641 saveImages(
1642 smallImage, article.getSmallImageId(), smallFile, smallBytes);
1643
1644
1646 updateTagsAsset(userId, article, tagsEntries);
1647
1648
1650 if (incrementVersion) {
1651 sendEmail(article, articleURL, prefs, "requested");
1652 }
1653
1654
1656 try {
1657 if (article.isIndexable()) {
1658 if (article.isApproved()) {
1659 Indexer.updateArticle(
1660 article.getCompanyId(), article.getGroupId(),
1661 article.getArticleId(), article.getVersion(),
1662 article.getTitle(), article.getDescription(),
1663 article.getContent(), article.getType(),
1664 article.getDisplayDate(), tagsEntries);
1665 }
1666 else {
1667 Indexer.deleteArticle(
1668 article.getCompanyId(), article.getArticleId());
1669 }
1670 }
1671 }
1672 catch (IOException ioe) {
1673 _log.error("Indexing " + article.getPrimaryKey(), ioe);
1674 }
1675
1676 return article;
1677 }
1678
1679 public JournalArticle updateContent(
1680 long groupId, String articleId, double version, String content)
1681 throws PortalException, SystemException {
1682
1683 JournalArticle article = journalArticlePersistence.findByG_A_V(
1684 groupId, articleId, version);
1685
1686 article.setContent(content);
1687
1688 journalArticlePersistence.update(article);
1689
1690 return article;
1691 }
1692
1693 public void updateTagsAsset(
1694 long userId, JournalArticle article, String[] tagsEntries)
1695 throws PortalException, SystemException {
1696
1697 boolean updateAsset = true;
1698
1699 if (article.getVersion() == 1) {
1700 }
1701 else if (!article.isApproved()) {
1702 updateAsset = false;
1703 }
1704 else if (!isLatestVersion(
1705 article.getGroupId(), article.getArticleId(),
1706 article.getVersion(), Boolean.TRUE)) {
1707
1708 updateAsset = false;
1709 }
1710
1711 if (updateAsset) {
1712 tagsAssetLocalService.updateAsset(
1713 userId, article.getGroupId(), JournalArticle.class.getName(),
1714 article.getResourcePrimKey(), tagsEntries, null, null,
1715 article.getDisplayDate(), article.getExpirationDate(),
1716 ContentTypes.TEXT_HTML, article.getTitle(),
1717 article.getDescription(), null, null, 0, 0, null, false);
1718 }
1719 }
1720
1721 protected void checkStructure(JournalArticle article)
1722 throws DocumentException, PortalException, SystemException {
1723
1724 JournalStructure structure = journalStructurePersistence.findByG_S(
1725 article.getGroupId(), article.getStructureId());
1726
1727 String content = GetterUtil.getString(article.getContent());
1728
1729 SAXReader reader = new SAXReader();
1730
1731 Document contentDoc = reader.read(new StringReader(content));
1732 Document xsdDoc = reader.read(new StringReader(structure.getXsd()));
1733
1734 try {
1735 checkStructure(contentDoc, xsdDoc.getRootElement());
1736 }
1737 catch (StructureXsdException sxsde) {
1738 long groupId = article.getGroupId();
1739 String articleId = article.getArticleId();
1740 double version = article.getVersion();
1741
1742 _log.error(
1743 "Article {groupId=" + groupId + ", articleId=" + articleId +
1744 ", version=" + version +
1745 "} has content that does not match its structure: " +
1746 sxsde.getMessage());
1747 }
1748 }
1749
1750 protected void checkStructure(Document contentDoc, Element root)
1751 throws PortalException {
1752
1753 Iterator itr = root.elements().iterator();
1754
1755 while (itr.hasNext()) {
1756 Element el = (Element)itr.next();
1757
1758 checkStructureField(el, contentDoc);
1759
1760 checkStructure(contentDoc, el);
1761 }
1762 }
1763
1764 protected void checkStructureField(Element el, Document contentDoc)
1765 throws PortalException {
1766
1767 StringMaker elPath = new StringMaker();
1768
1769 elPath.append(el.attributeValue("name"));
1770
1771 Element elParent = (Element)el.getParent();
1772
1773 for (;;) {
1774 if ((elParent == null) ||
1775 (elParent.getName().equals("root"))) {
1776
1777 break;
1778 }
1779
1780 elPath.insert(
1781 0, elParent.attributeValue("name") + StringPool.COMMA);
1782
1783 elParent = (Element)elParent.getParent();
1784 }
1785
1786 String[] elPathNames = StringUtil.split(elPath.toString());
1787
1788 Element contentEl = contentDoc.getRootElement();
1789
1790 for (int i = 0; i < elPathNames.length; i++) {
1791 boolean foundEl = false;
1792
1793 Iterator itr = contentEl.elements().iterator();
1794
1795 while (itr.hasNext()) {
1796 Element tempEl = (Element)itr.next();
1797
1798 if (elPathNames[i].equals(
1799 tempEl.attributeValue("name", StringPool.BLANK))) {
1800
1801 contentEl = tempEl;
1802 foundEl = true;
1803
1804 break;
1805 }
1806 }
1807
1808 if (!foundEl) {
1809 String elType = contentEl.attributeValue(
1810 "type", StringPool.BLANK);
1811
1812 if (!elType.equals("list") && !elType.equals("multi-list")) {
1813 throw new StructureXsdException(elPath.toString());
1814 }
1815
1816 break;
1817 }
1818 }
1819 }
1820
1821 protected String format(
1822 long groupId, String articleId, double version,
1823 boolean incrementVersion, String content, String structureId,
1824 Map images)
1825 throws SystemException {
1826
1827 if (Validator.isNotNull(structureId)) {
1828 SAXReader reader = new SAXReader();
1829
1830 Document doc = null;
1831
1832 try {
1833 doc = reader.read(new StringReader(content));
1834
1835 Element root = doc.getRootElement();
1836
1837 format(
1838 groupId, articleId, version, incrementVersion,
1839 root, images);
1840
1841 content = JournalUtil.formatXML(doc);
1842 }
1843 catch (DocumentException de) {
1844 _log.error(de);
1845 }
1846 catch (IOException ioe) {
1847 _log.error(ioe);
1848 }
1849 }
1850
1851 content = Html.replaceMsWordCharacters(content);
1852
1853 return content;
1854 }
1855
1856 protected void format(
1857 long groupId, String articleId, double version,
1858 boolean incrementVersion, Element root, Map images)
1859 throws SystemException {
1860
1861 Iterator itr = root.elements().iterator();
1862
1863 while (itr.hasNext()) {
1864 Element el = (Element)itr.next();
1865
1866 String elName = el.attributeValue("name", StringPool.BLANK);
1867 String elType = el.attributeValue("type", StringPool.BLANK);
1868
1869 if (elType.equals("image")) {
1870 formatImage(
1871 groupId, articleId, version, incrementVersion, el, elName,
1872 images);
1873 }
1874
1894
1895 format(
1896 groupId, articleId, version, incrementVersion, el, images);
1897 }
1898 }
1899
1900 protected void formatImage(
1901 long groupId, String articleId, double version,
1902 boolean incrementVersion, Element el, String elName, Map images)
1903 throws SystemException {
1904
1905 List imageContents = el.elements("dynamic-content");
1906
1907 Iterator itr = imageContents.listIterator();
1908
1909 while (itr.hasNext()) {
1910 Element dynamicContent = (Element)itr.next();
1911
1912 String elLanguage = dynamicContent.attributeValue(
1913 "language-id", StringPool.BLANK);
1914
1915 if (!elLanguage.equals(StringPool.BLANK)) {
1916 elLanguage = "_" + elLanguage;
1917 }
1918
1919 long imageId =
1920 journalArticleImageLocalService.getArticleImageId(
1921 groupId, articleId, version, elName, elLanguage);
1922
1923 double oldVersion = MathUtil.format(version - 0.1, 1, 1);
1924
1925 long oldImageId = 0;
1926
1927 if (oldVersion >= 1) {
1928 oldImageId =
1929 journalArticleImageLocalService.getArticleImageId(
1930 groupId, articleId, oldVersion, elName, elLanguage);
1931 }
1932
1933 String elContent =
1934 "/image/journal/article?img_id=" + imageId + "&t=" +
1935 ImageServletTokenUtil.getToken(imageId);
1936
1937 if (dynamicContent.getText().equals("delete")) {
1938 dynamicContent.setText(StringPool.BLANK);
1939
1940 ImageLocalUtil.deleteImage(imageId);
1941
1942 String defaultElLanguage = "";
1943
1944 if (!Validator.isNotNull(elLanguage)) {
1945 defaultElLanguage =
1946 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
1947 }
1948
1949 long defaultImageId =
1950 journalArticleImageLocalService.getArticleImageId(
1951 groupId, articleId, version, elName, defaultElLanguage);
1952
1953 ImageLocalUtil.deleteImage(defaultImageId);
1954
1955 continue;
1956 }
1957
1958 byte[] bytes = (byte[])images.get(elName + elLanguage);
1959
1960 if (bytes != null && (bytes.length > 0)) {
1961 dynamicContent.setText(elContent);
1962 dynamicContent.addAttribute("id", String.valueOf(imageId));
1963
1964 ImageLocalUtil.updateImage(imageId, bytes);
1965
1966 continue;
1967 }
1968
1969 if ((version > JournalArticleImpl.DEFAULT_VERSION) &&
1970 (incrementVersion)) {
1971
1972 Image oldImage = null;
1973
1974 if (oldImageId > 0) {
1975 oldImage = ImageLocalUtil.getImage(oldImageId);
1976 }
1977
1978 if (oldImage != null) {
1979 dynamicContent.setText(elContent);
1980 dynamicContent.addAttribute("id", String.valueOf(imageId));
1981
1982 bytes = oldImage.getTextObj();
1983
1984 ImageLocalUtil.updateImage(imageId, bytes);
1985 }
1986
1987 continue;
1988 }
1989
1990 Image image = ImageLocalUtil.getImage(imageId);
1991
1992 if (image != null) {
1993 dynamicContent.setText(elContent);
1994 dynamicContent.addAttribute("id", String.valueOf(imageId));
1995
1996 continue;
1997 }
1998
1999 String defaultElLanguage = "";
2000
2001 if (!Validator.isNotNull(elLanguage)) {
2002 defaultElLanguage =
2003 "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2004 }
2005
2006 long defaultImageId =
2007 journalArticleImageLocalService.getArticleImageId(
2008 groupId, articleId, version, elName, defaultElLanguage);
2009
2010 Image defaultImage = ImageLocalUtil.getImage(defaultImageId);
2011
2012 if (defaultImage != null) {
2013 dynamicContent.setText(elContent);
2014 dynamicContent.addAttribute("id", String.valueOf(imageId));
2015
2016 bytes = defaultImage.getTextObj();
2017
2018 ImageLocalUtil.updateImage(imageId, bytes);
2019
2020 continue;
2021 }
2022
2023 dynamicContent.setText(StringPool.BLANK);
2024 }
2025 }
2026
2027 protected void saveImages(
2028 boolean smallImage, long smallImageId, File smallFile,
2029 byte[] smallBytes)
2030 throws SystemException {
2031
2032 if (smallImage) {
2033 if ((smallFile != null) && (smallBytes != null)) {
2034 ImageLocalUtil.updateImage(smallImageId, smallBytes);
2035 }
2036 }
2037 else {
2038 ImageLocalUtil.deleteImage(smallImageId);
2039 }
2040 }
2041
2042 protected void sendEmail(
2043 JournalArticle article, String articleURL, PortletPreferences prefs,
2044 String emailType)
2045 throws PortalException, SystemException {
2046
2047 try {
2048 if (prefs == null) {
2049 return;
2050 }
2051 else if (emailType.equals("denied") &&
2052 JournalUtil.getEmailArticleApprovalDeniedEnabled(prefs)) {
2053 }
2054 else if (emailType.equals("granted") &&
2055 JournalUtil.getEmailArticleApprovalGrantedEnabled(prefs)) {
2056 }
2057 else if (emailType.equals("requested") &&
2058 JournalUtil.getEmailArticleApprovalRequestedEnabled(
2059 prefs)) {
2060 }
2061 else if (emailType.equals("review") &&
2062 JournalUtil.getEmailArticleReviewEnabled(prefs)) {
2063 }
2064 else {
2065 return;
2066 }
2067
2068 Company company = companyPersistence.findByPrimaryKey(
2069 article.getCompanyId());
2070
2071 User user = userPersistence.findByPrimaryKey(article.getUserId());
2072
2073 articleURL +=
2074 "&groupId=" + article.getGroupId() + "&articleId=" +
2075 article.getArticleId() + "&version=" + article.getVersion();
2076
2077 String portletName = PortalUtil.getPortletTitle(
2078 PortletKeys.JOURNAL, user);
2079
2080 String fromName = JournalUtil.getEmailFromName(prefs);
2081 String fromAddress = JournalUtil.getEmailFromAddress(prefs);
2082
2083 String toName = user.getFullName();
2084 String toAddress = user.getEmailAddress();
2085
2086 if (emailType.equals("requested") ||
2087 emailType.equals("review")) {
2088
2089 String tempToName = fromName;
2090 String tempToAddress = fromAddress;
2091
2092 fromName = toName;
2093 fromAddress = toAddress;
2094
2095 toName = tempToName;
2096 toAddress = tempToAddress;
2097 }
2098
2099 String subject = null;
2100 String body = null;
2101
2102 if (emailType.equals("denied")) {
2103 subject =
2104 JournalUtil.getEmailArticleApprovalDeniedSubject(prefs);
2105 body = JournalUtil.getEmailArticleApprovalDeniedBody(prefs);
2106 }
2107 else if (emailType.equals("granted")) {
2108 subject =
2109 JournalUtil.getEmailArticleApprovalGrantedSubject(prefs);
2110 body = JournalUtil.getEmailArticleApprovalGrantedBody(prefs);
2111 }
2112 else if (emailType.equals("requested")) {
2113 subject =
2114 JournalUtil.getEmailArticleApprovalRequestedSubject(prefs);
2115 body = JournalUtil.getEmailArticleApprovalRequestedBody(prefs);
2116 }
2117 else if (emailType.equals("review")) {
2118 subject = JournalUtil.getEmailArticleReviewSubject(prefs);
2119 body = JournalUtil.getEmailArticleReviewBody(prefs);
2120 }
2121
2122 subject = StringUtil.replace(
2123 subject,
2124 new String[] {
2125 "[$ARTICLE_ID$]",
2126 "[$ARTICLE_TITLE$]",
2127 "[$ARTICLE_URL$]",
2128 "[$ARTICLE_VERSION$]",
2129 "[$FROM_ADDRESS$]",
2130 "[$FROM_NAME$]",
2131 "[$PORTAL_URL$]",
2132 "[$PORTLET_NAME$]",
2133 "[$TO_ADDRESS$]",
2134 "[$TO_NAME$]"
2135 },
2136 new String[] {
2137 article.getArticleId(),
2138 article.getTitle(),
2139 articleURL,
2140 String.valueOf(article.getVersion()),
2141 fromAddress,
2142 fromName,
2143 company.getVirtualHost(),
2144 portletName,
2145 toAddress,
2146 toName,
2147 });
2148
2149 body = StringUtil.replace(
2150 body,
2151 new String[] {
2152 "[$ARTICLE_ID$]",
2153 "[$ARTICLE_TITLE$]",
2154 "[$ARTICLE_URL$]",
2155 "[$ARTICLE_VERSION$]",
2156 "[$FROM_ADDRESS$]",
2157 "[$FROM_NAME$]",
2158 "[$PORTAL_URL$]",
2159 "[$PORTLET_NAME$]",
2160 "[$TO_ADDRESS$]",
2161 "[$TO_NAME$]"
2162 },
2163 new String[] {
2164 article.getArticleId(),
2165 article.getTitle(),
2166 articleURL,
2167 String.valueOf(article.getVersion()),
2168 fromAddress,
2169 fromName,
2170 company.getVirtualHost(),
2171 portletName,
2172 toAddress,
2173 toName,
2174 });
2175
2176 InternetAddress from = new InternetAddress(fromAddress, fromName);
2177
2178 InternetAddress to = new InternetAddress(toAddress, toName);
2179
2180 MailMessage message = new MailMessage(
2181 from, to, subject, body, true);
2182
2183 mailService.sendEmail(message);
2184 }
2185 catch (IOException ioe) {
2186 throw new SystemException(ioe);
2187 }
2188 catch (PortalException pe) {
2189 throw pe;
2190 }
2191 }
2192
2193 protected void validate(
2194 long groupId, String articleId, boolean autoArticleId, String title,
2195 String content, String type, String structureId, String templateId,
2196 boolean smallImage, String smallImageURL, File smallFile,
2197 byte[] smallBytes)
2198 throws PortalException, SystemException {
2199
2200 if (!autoArticleId) {
2201 if ((Validator.isNull(articleId)) ||
2202 (Validator.isNumber(articleId)) ||
2203 (articleId.indexOf(StringPool.SPACE) != -1)) {
2204
2205 throw new ArticleIdException();
2206 }
2207
2208 try {
2209 journalArticlePersistence.findByG_A_V(
2210 groupId, articleId, JournalArticleImpl.DEFAULT_VERSION);
2211
2212 throw new DuplicateArticleIdException();
2213 }
2214 catch (NoSuchArticleException nste) {
2215 }
2216 }
2217
2218 validate(
2219 groupId, title, content, type, structureId, templateId,
2220 smallImage, smallImageURL, smallFile, smallBytes);
2221 }
2222
2223 protected void validate(
2224 long groupId, String title, String content, String type,
2225 String structureId, String templateId, boolean smallImage,
2226 String smallImageURL, File smallFile, byte[] smallBytes)
2227 throws PortalException, SystemException {
2228
2229 if (Validator.isNull(title)) {
2230 throw new ArticleTitleException();
2231 }
2232 else if (Validator.isNull(content)) {
2233 throw new ArticleContentException();
2234 }
2235 else if (Validator.isNull(type)) {
2236 throw new ArticleTypeException();
2237 }
2238
2239 if (Validator.isNotNull(structureId)) {
2240 journalStructurePersistence.findByG_S(groupId, structureId);
2241
2242 JournalTemplate template = journalTemplatePersistence.findByG_T(
2243 groupId, templateId);
2244
2245 if (!template.getStructureId().equals(structureId)) {
2246 throw new NoSuchTemplateException();
2247 }
2248 }
2249
2250 String[] imageExtensions =
2251 PropsUtil.getArray(PropsUtil.JOURNAL_IMAGE_EXTENSIONS);
2252
2253 if (smallImage && Validator.isNull(smallImageURL) &&
2254 smallFile != null && smallBytes != null) {
2255
2256 String smallImageName = smallFile.getName();
2257
2258 if (smallImageName != null) {
2259 boolean validSmallImageExtension = false;
2260
2261 for (int i = 0; i < imageExtensions.length; i++) {
2262 if (StringPool.STAR.equals(imageExtensions[i]) ||
2263 StringUtil.endsWith(
2264 smallImageName, imageExtensions[i])) {
2265
2266 validSmallImageExtension = true;
2267
2268 break;
2269 }
2270 }
2271
2272 if (!validSmallImageExtension) {
2273 throw new ArticleSmallImageNameException(smallImageName);
2274 }
2275 }
2276
2277 long smallImageMaxSize = GetterUtil.getLong(
2278 PropsUtil.get(PropsUtil.JOURNAL_IMAGE_SMALL_MAX_SIZE));
2279
2280 if ((smallImageMaxSize > 0) &&
2281 ((smallBytes == null) ||
2282 (smallBytes.length > smallImageMaxSize))) {
2283
2284 throw new ArticleSmallImageSizeException();
2285 }
2286 }
2287 }
2288
2289 private static final String _TOKEN_PAGE_BREAK = PropsUtil.get(
2290 PropsUtil.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
2291
2292 private static Log _log =
2293 LogFactory.getLog(JournalArticleLocalServiceImpl.class);
2294
2295}