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