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         // Lucene
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         // Lucene
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         // Lucene
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                        com.liferay.portal.kernel.search.Document doc =
1473                            Indexer.getArticleDocument(
1474                                companyId, groupId, articleId, version, title,
1475                                description, content, type, displayDate,
1476                                tagsEntries);
1477
1478                        SearchEngineUtil.addDocument(companyId, doc);
1479                    }
1480                    catch (Exception e1) {
1481                        _log.error("Reindexing " + article.getId(), e1);
1482                    }
1483                }
1484            }
1485        }
1486        catch (SystemException se) {
1487            throw se;
1488        }
1489        catch (Exception e2) {
1490            throw new SystemException(e2);
1491        }
1492    }
1493
1494    public JournalArticle removeArticleLocale(
1495            long groupId, String articleId, double version, String languageId)
1496        throws PortalException, SystemException {
1497
1498        JournalArticle article = journalArticlePersistence.findByG_A_V(
1499            groupId, articleId, version);
1500
1501        String content = article.getContent();
1502
1503        if (article.isTemplateDriven()) {
1504            content = JournalUtil.removeArticleLocale(content, languageId);
1505        }
1506        else {
1507            content = LocalizationUtil.removeLocalization(
1508                content, "static-content", languageId, true);
1509        }
1510
1511        article.setContent(content);
1512
1513        journalArticlePersistence.update(article, false);
1514
1515        return article;
1516    }
1517
1518    public Hits search(
1519            long companyId, long groupId, String keywords, int start, int end)
1520        throws SystemException {
1521
1522        return search(
1523            companyId, groupId, keywords, "displayDate", Sort.LONG_TYPE, start,
1524            end);
1525    }
1526
1527    public Hits search(
1528            long companyId, long groupId, String keywords, String sortField,
1529            int sortType, int start, int end)
1530        throws SystemException {
1531
1532        try {
1533            BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
1534
1535            contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
1536
1537            if (groupId > 0) {
1538                contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
1539            }
1540
1541            BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
1542
1543            if (Validator.isNotNull(keywords)) {
1544                searchQuery.addTerm(Field.TITLE, keywords);
1545                searchQuery.addTerm(Field.CONTENT, keywords);
1546                searchQuery.addTerm(Field.DESCRIPTION, keywords);
1547                searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
1548            }
1549
1550            BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
1551
1552            fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
1553
1554            if (searchQuery.clauses().size() > 0) {
1555                fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
1556            }
1557
1558            Sort sort = new Sort(sortField, sortType, true);
1559
1560            return SearchEngineUtil.search(
1561                companyId, fullQuery, sort, start, end);
1562        }
1563        catch (Exception e) {
1564            throw new SystemException(e);
1565        }
1566    }
1567
1568    public List<JournalArticle> search(
1569            long companyId, long groupId, String keywords, Double version,
1570            String type, String structureId, String templateId,
1571            Date displayDateGT, Date displayDateLT, Boolean approved,
1572            Boolean expired, Date reviewDate, int start, int end,
1573            OrderByComparator obc)
1574        throws SystemException {
1575
1576        return journalArticleFinder.findByKeywords(
1577            companyId, groupId, keywords, version, type, structureId,
1578            templateId, displayDateGT, displayDateLT, approved, expired,
1579            reviewDate, start, end, obc);
1580    }
1581
1582    public List<JournalArticle> search(
1583            long companyId, long groupId, String articleId, Double version,
1584            String title, String description, String content, String type,
1585            String structureId, String templateId, Date displayDateGT,
1586            Date displayDateLT, Boolean approved, Boolean expired,
1587            Date reviewDate, boolean andOperator, int start, int end,
1588            OrderByComparator obc)
1589        throws SystemException {
1590
1591        return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1592            companyId, groupId, articleId, version, title, description, content,
1593            type, structureId, templateId, displayDateGT, displayDateLT,
1594            approved, expired, reviewDate, andOperator, start, end, obc);
1595    }
1596
1597    public List<JournalArticle> search(
1598            long companyId, long groupId, String articleId, Double version,
1599            String title, String description, String content, String type,
1600            String[] structureIds, String[] templateIds, Date displayDateGT,
1601            Date displayDateLT, Boolean approved, Boolean expired,
1602            Date reviewDate, boolean andOperator, int start, int end,
1603            OrderByComparator obc)
1604        throws SystemException {
1605
1606        return journalArticleFinder.findByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1607            companyId, groupId, articleId, version, title, description, content,
1608            type, structureIds, templateIds, displayDateGT, displayDateLT,
1609            approved, expired, reviewDate, andOperator, start, end, obc);
1610    }
1611
1612    public int searchCount(
1613            long companyId, long groupId, String keywords, Double version,
1614            String type, String structureId, String templateId,
1615            Date displayDateGT, Date displayDateLT, Boolean approved,
1616            Boolean expired, Date reviewDate)
1617        throws SystemException {
1618
1619        return journalArticleFinder.countByKeywords(
1620            companyId, groupId, keywords, version, type, structureId,
1621            templateId, displayDateGT, displayDateLT, approved, expired,
1622            reviewDate);
1623    }
1624
1625    public int searchCount(
1626            long companyId, long groupId, String articleId, Double version,
1627            String title, String description, String content, String type,
1628            String structureId, String templateId, Date displayDateGT,
1629            Date displayDateLT, Boolean approved, Boolean expired,
1630            Date reviewDate, boolean andOperator)
1631        throws SystemException {
1632
1633        return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1634            companyId, groupId, articleId, version, title, description, content,
1635            type, structureId, templateId, displayDateGT, displayDateLT,
1636            approved, expired, reviewDate, andOperator);
1637    }
1638
1639    public int searchCount(
1640            long companyId, long groupId, String articleId, Double version,
1641            String title, String description, String content, String type,
1642            String[] structureIds, String[] templateIds, Date displayDateGT,
1643            Date displayDateLT, Boolean approved, Boolean expired,
1644            Date reviewDate, boolean andOperator)
1645        throws SystemException {
1646
1647        return journalArticleFinder.countByC_G_A_V_T_D_C_T_S_T_D_A_E_R(
1648            companyId, groupId, articleId, version, title, description, content,
1649            type, structureIds, templateIds, displayDateGT, displayDateLT,
1650            approved, expired, reviewDate, andOperator);
1651    }
1652
1653    public JournalArticle updateArticle(
1654            long userId, long groupId, String articleId, double version,
1655            boolean incrementVersion, String title, String description,
1656            String content, String type, String structureId, String templateId,
1657            int displayDateMonth, int displayDateDay, int displayDateYear,
1658            int displayDateHour, int displayDateMinute, int expirationDateMonth,
1659            int expirationDateDay, int expirationDateYear,
1660            int expirationDateHour, int expirationDateMinute,
1661            boolean neverExpire, int reviewDateMonth, int reviewDateDay,
1662            int reviewDateYear, int reviewDateHour, int reviewDateMinute,
1663            boolean neverReview, boolean indexable, boolean smallImage,
1664            String smallImageURL, File smallFile, Map<String, byte[]> images,
1665            String articleURL, PortletPreferences prefs, String[] tagsEntries)
1666        throws PortalException, SystemException {
1667
1668        // Article
1669
1670        User user = userPersistence.findByPrimaryKey(userId);
1671        articleId = articleId.trim().toUpperCase();
1672
1673        Date displayDate = PortalUtil.getDate(
1674            displayDateMonth, displayDateDay, displayDateYear,
1675            displayDateHour, displayDateMinute, user.getTimeZone(),
1676            new ArticleDisplayDateException());
1677
1678        Date expirationDate = null;
1679
1680        if (!neverExpire) {
1681            expirationDate = PortalUtil.getDate(
1682                expirationDateMonth, expirationDateDay, expirationDateYear,
1683                expirationDateHour, expirationDateMinute, user.getTimeZone(),
1684                new ArticleExpirationDateException());
1685        }
1686
1687        Date reviewDate = null;
1688
1689        if (!neverReview) {
1690            reviewDate = PortalUtil.getDate(
1691                reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1692                reviewDateMinute, user.getTimeZone(),
1693                new ArticleReviewDateException());
1694        }
1695
1696        byte[] smallBytes = null;
1697
1698        try {
1699            smallBytes = FileUtil.getBytes(smallFile);
1700        }
1701        catch (IOException ioe) {
1702        }
1703
1704        Date now = new Date();
1705
1706        validate(
1707            groupId, title, content, type, structureId, templateId, smallImage,
1708            smallImageURL, smallFile, smallBytes);
1709
1710        JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
1711            groupId, articleId, version);
1712
1713        JournalArticle article = null;
1714
1715        if (incrementVersion) {
1716            double latestVersion = getLatestVersion(groupId, articleId);
1717
1718            long id = counterLocalService.increment();
1719
1720            article = journalArticlePersistence.create(id);
1721
1722            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1723            article.setGroupId(oldArticle.getGroupId());
1724            article.setCompanyId(user.getCompanyId());
1725            article.setUserId(user.getUserId());
1726            article.setUserName(user.getFullName());
1727            article.setCreateDate(now);
1728            article.setArticleId(articleId);
1729            article.setVersion(MathUtil.format(latestVersion + 0.1, 1, 1));
1730            article.setSmallImageId(oldArticle.getSmallImageId());
1731        }
1732        else {
1733            article = oldArticle;
1734        }
1735
1736        content = format(
1737            groupId, articleId, article.getVersion(), incrementVersion, content,
1738            structureId, images);
1739
1740        boolean approved = oldArticle.isApproved();
1741
1742        if (incrementVersion) {
1743            approved = false;
1744        }
1745
1746        article.setModifiedDate(now);
1747        article.setTitle(title);
1748        article.setDescription(description);
1749        article.setContent(content);
1750        article.setType(type);
1751        article.setStructureId(structureId);
1752        article.setTemplateId(templateId);
1753        article.setDisplayDate(displayDate);
1754        article.setApproved(approved);
1755
1756        if ((expirationDate == null) || expirationDate.after(now)) {
1757            article.setExpired(false);
1758        }
1759        else {
1760            article.setExpired(true);
1761        }
1762
1763        article.setExpirationDate(expirationDate);
1764        article.setReviewDate(reviewDate);
1765        article.setIndexable(indexable);
1766        article.setSmallImage(smallImage);
1767
1768        if (article.getSmallImageId() == 0) {
1769            article.setSmallImageId(counterLocalService.increment());
1770        }
1771
1772        article.setSmallImageURL(smallImageURL);
1773
1774        journalArticlePersistence.update(article, false);
1775
1776        // Small image
1777
1778        saveImages(
1779            smallImage, article.getSmallImageId(), smallFile, smallBytes);
1780
1781        // Tags
1782
1783        updateTagsAsset(userId, article, tagsEntries);
1784
1785        // Email
1786
1787        if (incrementVersion) {
1788            try {
1789                sendEmail(article, articleURL, prefs, "requested");
1790            }
1791            catch (IOException ioe) {
1792                throw new SystemException(ioe);
1793            }
1794        }
1795
1796        // Lucene
1797
1798        try {
1799            if (article.isIndexable()) {
1800                if (article.isApproved()) {
1801                    Indexer.updateArticle(
1802                        article.getCompanyId(), article.getGroupId(),
1803                        article.getArticleId(), article.getVersion(),
1804                        article.getTitle(), article.getDescription(),
1805                        article.getContent(), article.getType(),
1806                        article.getDisplayDate(), tagsEntries);
1807                }
1808                else {
1809                    Indexer.deleteArticle(
1810                        article.getCompanyId(), article.getArticleId());
1811                }
1812            }
1813        }
1814        catch (SearchException se) {
1815            _log.error("Indexing " + article.getPrimaryKey(), se);
1816        }
1817
1818        return article;
1819    }
1820
1821    public JournalArticle updateContent(
1822            long groupId, String articleId, double version, String content)
1823        throws PortalException, SystemException {
1824
1825        JournalArticle article = journalArticlePersistence.findByG_A_V(
1826            groupId, articleId, version);
1827
1828        article.setContent(content);
1829
1830        journalArticlePersistence.update(article, false);
1831
1832        return article;
1833    }
1834
1835    public void updateTagsAsset(
1836            long userId, JournalArticle article, String[] tagsEntries)
1837        throws PortalException, SystemException {
1838
1839        // Get the earliest display date and latest expiration date among
1840        // all article versions
1841
1842        Date[] dateInterval = getDateInterval(
1843            article.getGroupId(), article.getArticleId(),
1844            article.getDisplayDate(), article.getExpirationDate());
1845
1846        Date displayDate = dateInterval[0];
1847        Date expirationDate = dateInterval[1];
1848
1849        tagsAssetLocalService.updateAsset(
1850            userId, article.getGroupId(), JournalArticle.class.getName(),
1851            article.getResourcePrimKey(), tagsEntries, null, null,
1852            displayDate, expirationDate, ContentTypes.TEXT_HTML,
1853            article.getTitle(), article.getDescription(), null, null, 0, 0,
1854            null, false);
1855    }
1856
1857    protected void checkStructure(JournalArticle article)
1858        throws DocumentException, PortalException, SystemException {
1859
1860        JournalStructure structure = journalStructurePersistence.findByG_S(
1861            article.getGroupId(), article.getStructureId());
1862
1863        String content = GetterUtil.getString(article.getContent());
1864
1865        Document contentDoc = SAXReaderUtil.read(content);
1866        Document xsdDoc = SAXReaderUtil.read(structure.getXsd());
1867
1868        try {
1869            checkStructure(contentDoc, xsdDoc.getRootElement());
1870        }
1871        catch (StructureXsdException sxsde) {
1872            long groupId = article.getGroupId();
1873            String articleId = article.getArticleId();
1874            double version = article.getVersion();
1875
1876            if (_log.isWarnEnabled()) {
1877                _log.warn(
1878                    "Article {groupId=" + groupId + ", articleId=" +
1879                        articleId + ", version=" + version +
1880                            "} has content that does not match its " +
1881                                "structure: " + sxsde.getMessage());
1882            }
1883        }
1884    }
1885
1886    protected void checkStructure(Document contentDoc, Element root)
1887        throws PortalException {
1888
1889        for (Element el : root.elements()) {
1890            checkStructureField(el, contentDoc);
1891
1892            checkStructure(contentDoc, el);
1893        }
1894    }
1895
1896    protected void checkStructureField(Element el, Document contentDoc)
1897        throws PortalException {
1898
1899        StringBuilder elPath = new StringBuilder();
1900
1901        elPath.append(el.attributeValue("name"));
1902
1903        Element elParent = el.getParent();
1904
1905        for (;;) {
1906            if ((elParent == null) ||
1907                (elParent.getName().equals("root"))) {
1908
1909                break;
1910            }
1911
1912            elPath.insert(
1913                0, elParent.attributeValue("name") + StringPool.COMMA);
1914
1915            elParent = elParent.getParent();
1916        }
1917
1918        String[] elPathNames = StringUtil.split(elPath.toString());
1919
1920        Element contentEl = contentDoc.getRootElement();
1921
1922        for (int i = 0; i < elPathNames.length; i++) {
1923            boolean foundEl = false;
1924
1925            for (Element tempEl : contentEl.elements()) {
1926                if (elPathNames[i].equals(
1927                        tempEl.attributeValue("name", StringPool.BLANK))) {
1928
1929                    contentEl = tempEl;
1930                    foundEl = true;
1931
1932                    break;
1933                }
1934            }
1935
1936            if (!foundEl) {
1937                String elType = contentEl.attributeValue(
1938                    "type", StringPool.BLANK);
1939
1940                if (!elType.equals("list") && !elType.equals("multi-list")) {
1941                    throw new StructureXsdException(elPath.toString());
1942                }
1943
1944                break;
1945            }
1946        }
1947    }
1948
1949    protected void copyArticleImages(
1950            JournalArticle oldArticle, JournalArticle newArticle)
1951        throws Exception {
1952
1953        Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
1954
1955        XPath xpathSelector = SAXReaderUtil.createXPath(
1956            "//dynamic-element[@type='image']");
1957
1958        List<Node> imageNodes = xpathSelector.selectNodes(contentDoc);
1959
1960        for (Node imageNode : imageNodes) {
1961            Element imageEl = (Element)imageNode;
1962
1963            String name = imageEl.attributeValue("name");
1964
1965            List<Element> dynamicContentEls = imageEl.elements(
1966                "dynamic-content");
1967
1968            for (Element dynamicContentEl : dynamicContentEls) {
1969                long imageId = GetterUtil.getLong(
1970                    dynamicContentEl.attributeValue("id"));
1971                String languageId = dynamicContentEl.attributeValue(
1972                    "language-id");
1973
1974                Image oldImage = null;
1975
1976                try {
1977                    oldImage = ImageLocalServiceUtil.getImage(imageId);
1978                }
1979                catch (NoSuchImageException nsie) {
1980                    continue;
1981                }
1982
1983                imageId = journalArticleImageLocalService.getArticleImageId(
1984                    newArticle.getGroupId(), newArticle.getArticleId(),
1985                    newArticle.getVersion(), name, languageId);
1986
1987                ImageLocalServiceUtil.updateImage(
1988                    imageId, oldImage.getTextObj());
1989
1990                String elContent =
1991                    "/image/journal/article?img_id=" + imageId + "&t=" +
1992                        ImageServletTokenUtil.getToken(imageId);
1993
1994                dynamicContentEl.setText(elContent);
1995                dynamicContentEl.addAttribute("id", String.valueOf(imageId));
1996            }
1997        }
1998
1999        newArticle.setContent(contentDoc.formattedString());
2000    }
2001
2002    protected String format(
2003            long groupId, String articleId, double version,
2004            boolean incrementVersion, String content, String structureId,
2005            Map<String, byte[]> images)
2006        throws PortalException, SystemException {
2007
2008        if (Validator.isNotNull(structureId)) {
2009            Document doc = null;
2010
2011            try {
2012                doc = SAXReaderUtil.read(content);
2013
2014                Element root = doc.getRootElement();
2015
2016                format(
2017                    groupId, articleId, version, incrementVersion, root,
2018                    images);
2019
2020                content = JournalUtil.formatXML(doc);
2021            }
2022            catch (DocumentException de) {
2023                _log.error(de);
2024            }
2025            catch (IOException ioe) {
2026                _log.error(ioe);
2027            }
2028        }
2029
2030        content = HtmlUtil.replaceMsWordCharacters(content);
2031
2032        return content;
2033    }
2034
2035    protected void format(
2036            long groupId, String articleId, double version,
2037            boolean incrementVersion, Element root, Map<String, byte[]> images)
2038        throws PortalException, SystemException {
2039
2040        for (Element el : root.elements()) {
2041            String elName = el.attributeValue("name", StringPool.BLANK);
2042            String elType = el.attributeValue("type", StringPool.BLANK);
2043
2044            if (elType.equals("image")) {
2045                formatImage(
2046                    groupId, articleId, version, incrementVersion, el, elName,
2047                    images);
2048            }
2049            /*else if (elType.equals("text_area")) {
2050                Element dynamicContent = el.element("dynamic-content");
2051
2052                String text = dynamicContent.getText();
2053
2054                // LEP-1594
2055
2056                try {
2057                    text = ParserUtils.trimTags(
2058                        text, new String[] {"script"}, false, true);
2059                }
2060                catch (ParserException pe) {
2061                    text = pe.getLocalizedMessage();
2062                }
2063                catch (UnsupportedEncodingException uee) {
2064                    text = uee.getLocalizedMessage();
2065                }
2066
2067                dynamicContent.setText(text);
2068            }*/
2069
2070            format(groupId, articleId, version, incrementVersion, el, images);
2071        }
2072    }
2073
2074    protected void formatImage(
2075            long groupId, String articleId, double version,
2076            boolean incrementVersion, Element el, String elName,
2077            Map<String, byte[]> images)
2078        throws PortalException, SystemException {
2079
2080        List<Element> imageContents = el.elements("dynamic-content");
2081
2082        for (Element dynamicContent : imageContents) {
2083            String elLanguage = dynamicContent.attributeValue(
2084                "language-id", StringPool.BLANK);
2085
2086            if (!elLanguage.equals(StringPool.BLANK)) {
2087                elLanguage = "_" + elLanguage;
2088            }
2089
2090            long imageId =
2091                journalArticleImageLocalService.getArticleImageId(
2092                    groupId, articleId, version, elName, elLanguage);
2093
2094            double oldVersion = MathUtil.format(version - 0.1, 1, 1);
2095
2096            long oldImageId = 0;
2097
2098            if ((oldVersion >= 1) && incrementVersion) {
2099                oldImageId =
2100                    journalArticleImageLocalService.getArticleImageId(
2101                        groupId, articleId, oldVersion, elName, elLanguage);
2102            }
2103
2104            String elContent =
2105                "/image/journal/article?img_id=" + imageId + "&t=" +
2106                    ImageServletTokenUtil.getToken(imageId);
2107
2108            if (dynamicContent.getText().equals("delete")) {
2109                dynamicContent.setText(StringPool.BLANK);
2110
2111                imageLocalService.deleteImage(imageId);
2112
2113                String defaultElLanguage = "";
2114
2115                if (!Validator.isNotNull(elLanguage)) {
2116                    defaultElLanguage =
2117                        "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2118                }
2119
2120                long defaultImageId =
2121                    journalArticleImageLocalService.getArticleImageId(
2122                        groupId, articleId, version, elName, defaultElLanguage);
2123
2124                imageLocalService.deleteImage(defaultImageId);
2125
2126                continue;
2127            }
2128
2129            byte[] bytes = images.get(elName + elLanguage);
2130
2131            if (bytes != null && (bytes.length > 0)) {
2132                dynamicContent.setText(elContent);
2133                dynamicContent.addAttribute("id", String.valueOf(imageId));
2134
2135                imageLocalService.updateImage(imageId, bytes);
2136
2137                continue;
2138            }
2139
2140            if ((version > JournalArticleImpl.DEFAULT_VERSION) &&
2141                (incrementVersion)) {
2142
2143                Image oldImage = null;
2144
2145                if (oldImageId > 0) {
2146                    oldImage = imageLocalService.getImage(oldImageId);
2147                }
2148
2149                if (oldImage != null) {
2150                    dynamicContent.setText(elContent);
2151                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2152
2153                    bytes = oldImage.getTextObj();
2154
2155                    imageLocalService.updateImage(imageId, bytes);
2156                }
2157
2158                continue;
2159            }
2160
2161            Image image = imageLocalService.getImage(imageId);
2162
2163            if (image != null) {
2164                dynamicContent.setText(elContent);
2165                dynamicContent.addAttribute("id", String.valueOf(imageId));
2166
2167                continue;
2168            }
2169
2170            long contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2171                dynamicContent.getText(), "img_id"));
2172
2173            if (contentImageId <= 0) {
2174                contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2175                    dynamicContent.getText(), "img_id", false));
2176            }
2177
2178            if (contentImageId > 0) {
2179                image = imageLocalService.getImage(contentImageId);
2180
2181                if (image != null) {
2182                    dynamicContent.addAttribute(
2183                        "id", String.valueOf(contentImageId));
2184
2185                    continue;
2186                }
2187            }
2188
2189            String defaultElLanguage = "";
2190
2191            if (!Validator.isNotNull(elLanguage)) {
2192                defaultElLanguage =
2193                    "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2194            }
2195
2196            long defaultImageId =
2197                journalArticleImageLocalService.getArticleImageId(
2198                    groupId, articleId, version, elName, defaultElLanguage);
2199
2200            Image defaultImage = imageLocalService.getImage(defaultImageId);
2201
2202            if (defaultImage != null) {
2203                dynamicContent.setText(elContent);
2204                dynamicContent.addAttribute(
2205                    "id", String.valueOf(defaultImageId));
2206
2207                bytes = defaultImage.getTextObj();
2208
2209                imageLocalService.updateImage(defaultImageId, bytes);
2210
2211                continue;
2212            }
2213
2214            dynamicContent.setText(StringPool.BLANK);
2215        }
2216    }
2217
2218    protected Date[] getDateInterval(
2219            long groupId, String articleId, Date earliestDisplayDate,
2220            Date latestExpirationDate)
2221        throws SystemException {
2222
2223        Date[] dateInterval = new Date[2];
2224
2225        List<JournalArticle> articles = journalArticlePersistence.findByG_A_A(
2226            groupId, articleId, true);
2227
2228        boolean expiringArticle = true;
2229
2230        if (latestExpirationDate == null) {
2231            expiringArticle = false;
2232        }
2233
2234        for (JournalArticle article : articles) {
2235            if ((earliestDisplayDate == null) ||
2236                ((article.getDisplayDate() != null) &&
2237                 earliestDisplayDate.after(article.getDisplayDate()))) {
2238
2239                earliestDisplayDate = article.getDisplayDate();
2240            }
2241
2242            if (expiringArticle &&
2243                ((latestExpirationDate == null) ||
2244                 ((article.getExpirationDate() != null) &&
2245                  latestExpirationDate.before(article.getExpirationDate())))) {
2246
2247                latestExpirationDate = article.getExpirationDate();
2248            }
2249
2250            if (expiringArticle && (article.getExpirationDate() == null)) {
2251                latestExpirationDate = null;
2252                expiringArticle = false;
2253            }
2254        }
2255
2256        dateInterval[0] = earliestDisplayDate;
2257        dateInterval[1] = latestExpirationDate;
2258
2259        return dateInterval;
2260    }
2261
2262    protected void saveImages(
2263            boolean smallImage, long smallImageId, File smallFile,
2264            byte[] smallBytes)
2265        throws PortalException, SystemException {
2266
2267        if (smallImage) {
2268            if ((smallFile != null) && (smallBytes != null)) {
2269                imageLocalService.updateImage(smallImageId, smallBytes);
2270            }
2271        }
2272        else {
2273            imageLocalService.deleteImage(smallImageId);
2274        }
2275    }
2276
2277    protected void sendEmail(
2278            JournalArticle article, String articleURL, PortletPreferences prefs,
2279            String emailType)
2280        throws IOException, PortalException, SystemException {
2281
2282        if (prefs == null) {
2283            return;
2284        }
2285        else if (emailType.equals("denied") &&
2286            JournalUtil.getEmailArticleApprovalDeniedEnabled(prefs)) {
2287        }
2288        else if (emailType.equals("granted") &&
2289                 JournalUtil.getEmailArticleApprovalGrantedEnabled(prefs)) {
2290        }
2291        else if (emailType.equals("requested") &&
2292                 JournalUtil.getEmailArticleApprovalRequestedEnabled(prefs)) {
2293        }
2294        else if (emailType.equals("review") &&
2295                 JournalUtil.getEmailArticleReviewEnabled(prefs)) {
2296        }
2297        else {
2298            return;
2299        }
2300
2301        Company company = companyPersistence.findByPrimaryKey(
2302            article.getCompanyId());
2303
2304        User user = userPersistence.findByPrimaryKey(article.getUserId());
2305
2306        articleURL +=
2307            "&groupId=" + article.getGroupId() + "&articleId=" +
2308                article.getArticleId() + "&version=" + article.getVersion();
2309
2310        String portletName = PortalUtil.getPortletTitle(
2311            PortletKeys.JOURNAL, user);
2312
2313        String fromName = JournalUtil.getEmailFromName(prefs);
2314        String fromAddress = JournalUtil.getEmailFromAddress(prefs);
2315
2316        String toName = user.getFullName();
2317        String toAddress = user.getEmailAddress();
2318
2319        if (emailType.equals("requested") ||
2320            emailType.equals("review")) {
2321
2322            String tempToName = fromName;
2323            String tempToAddress = fromAddress;
2324
2325            fromName = toName;
2326            fromAddress = toAddress;
2327
2328            toName = tempToName;
2329            toAddress = tempToAddress;
2330        }
2331
2332        String subject = null;
2333        String body = null;
2334
2335        if (emailType.equals("denied")) {
2336            subject =
2337                JournalUtil.getEmailArticleApprovalDeniedSubject(prefs);
2338            body = JournalUtil.getEmailArticleApprovalDeniedBody(prefs);
2339        }
2340        else if (emailType.equals("granted")) {
2341            subject =
2342                JournalUtil.getEmailArticleApprovalGrantedSubject(prefs);
2343            body = JournalUtil.getEmailArticleApprovalGrantedBody(prefs);
2344        }
2345        else if (emailType.equals("requested")) {
2346            subject =
2347                JournalUtil.getEmailArticleApprovalRequestedSubject(prefs);
2348            body = JournalUtil.getEmailArticleApprovalRequestedBody(prefs);
2349        }
2350        else if (emailType.equals("review")) {
2351            subject = JournalUtil.getEmailArticleReviewSubject(prefs);
2352            body = JournalUtil.getEmailArticleReviewBody(prefs);
2353        }
2354
2355        subject = StringUtil.replace(
2356            subject,
2357            new String[] {
2358                "[$ARTICLE_ID$]",
2359                "[$ARTICLE_TITLE$]",
2360                "[$ARTICLE_URL$]",
2361                "[$ARTICLE_VERSION$]",
2362                "[$FROM_ADDRESS$]",
2363                "[$FROM_NAME$]",
2364                "[$PORTAL_URL$]",
2365                "[$PORTLET_NAME$]",
2366                "[$TO_ADDRESS$]",
2367                "[$TO_NAME$]"
2368            },
2369            new String[] {
2370                article.getArticleId(),
2371                article.getTitle(),
2372                articleURL,
2373                String.valueOf(article.getVersion()),
2374                fromAddress,
2375                fromName,
2376                company.getVirtualHost(),
2377                portletName,
2378                toAddress,
2379                toName,
2380            });
2381
2382        body = StringUtil.replace(
2383            body,
2384            new String[] {
2385                "[$ARTICLE_ID$]",
2386                "[$ARTICLE_TITLE$]",
2387                "[$ARTICLE_URL$]",
2388                "[$ARTICLE_VERSION$]",
2389                "[$FROM_ADDRESS$]",
2390                "[$FROM_NAME$]",
2391                "[$PORTAL_URL$]",
2392                "[$PORTLET_NAME$]",
2393                "[$TO_ADDRESS$]",
2394                "[$TO_NAME$]"
2395            },
2396            new String[] {
2397                article.getArticleId(),
2398                article.getTitle(),
2399                articleURL,
2400                String.valueOf(article.getVersion()),
2401                fromAddress,
2402                fromName,
2403                company.getVirtualHost(),
2404                portletName,
2405                toAddress,
2406                toName,
2407            });
2408
2409        InternetAddress from = new InternetAddress(fromAddress, fromName);
2410
2411        InternetAddress to = new InternetAddress(toAddress, toName);
2412
2413        MailMessage message = new MailMessage(from, to, subject, body, true);
2414
2415        mailService.sendEmail(message);
2416    }
2417
2418    protected void validate(String articleId) throws PortalException {
2419        if ((Validator.isNull(articleId)) ||
2420            (articleId.indexOf(StringPool.SPACE) != -1)) {
2421
2422            throw new ArticleIdException();
2423        }
2424    }
2425
2426    protected void validate(
2427            long groupId, String articleId, boolean autoArticleId,
2428            double version, String title, String content, String type,
2429            String structureId, String templateId, boolean smallImage,
2430            String smallImageURL, File smallFile, byte[] smallBytes)
2431        throws PortalException, SystemException {
2432
2433        if (!autoArticleId) {
2434            validate(articleId);
2435
2436            JournalArticle article = journalArticlePersistence.fetchByG_A_V(
2437                groupId, articleId, version);
2438
2439            if (article != null) {
2440                throw new DuplicateArticleIdException();
2441            }
2442        }
2443
2444        validate(
2445            groupId, title, content, type, structureId, templateId,
2446            smallImage, smallImageURL, smallFile, smallBytes);
2447    }
2448
2449    protected void validate(
2450            long groupId, String title, String content, String type,
2451            String structureId, String templateId, boolean smallImage,
2452            String smallImageURL, File smallFile, byte[] smallBytes)
2453        throws PortalException, SystemException {
2454
2455        if (Validator.isNull(title)) {
2456            throw new ArticleTitleException();
2457        }
2458        else if (Validator.isNull(content)) {
2459            throw new ArticleContentException();
2460        }
2461        else if (Validator.isNull(type)) {
2462            throw new ArticleTypeException();
2463        }
2464
2465        if (Validator.isNotNull(structureId)) {
2466            journalStructurePersistence.findByG_S(groupId, structureId);
2467
2468            JournalTemplate template = journalTemplatePersistence.findByG_T(
2469                groupId, templateId);
2470
2471            if (!template.getStructureId().equals(structureId)) {
2472                throw new NoSuchTemplateException();
2473            }
2474        }
2475
2476        String[] imageExtensions =
2477            PropsUtil.getArray(PropsKeys.JOURNAL_IMAGE_EXTENSIONS);
2478
2479        if (smallImage && Validator.isNull(smallImageURL) &&
2480            smallFile != null && smallBytes != null) {
2481
2482            String smallImageName = smallFile.getName();
2483
2484            if (smallImageName != null) {
2485                boolean validSmallImageExtension = false;
2486
2487                for (int i = 0; i < imageExtensions.length; i++) {
2488                    if (StringPool.STAR.equals(imageExtensions[i]) ||
2489                        StringUtil.endsWith(
2490                            smallImageName, imageExtensions[i])) {
2491
2492                        validSmallImageExtension = true;
2493
2494                        break;
2495                    }
2496                }
2497
2498                if (!validSmallImageExtension) {
2499                    throw new ArticleSmallImageNameException(smallImageName);
2500                }
2501            }
2502
2503            long smallImageMaxSize = GetterUtil.getLong(
2504                PropsUtil.get(PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE));
2505
2506            if ((smallImageMaxSize > 0) &&
2507                ((smallBytes == null) ||
2508                    (smallBytes.length > smallImageMaxSize))) {
2509
2510                throw new ArticleSmallImageSizeException();
2511            }
2512        }
2513    }
2514
2515    private static final String _TOKEN_PAGE_BREAK = PropsUtil.get(
2516        PropsKeys.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
2517
2518    private static Log _log =
2519        LogFactory.getLog(JournalArticleLocalServiceImpl.class);
2520
2521}