001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.service.impl;
016    
017    import com.liferay.portal.NoSuchImageException;
018    import com.liferay.portal.kernel.dao.orm.QueryUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
024    import com.liferay.portal.kernel.search.Field;
025    import com.liferay.portal.kernel.search.Hits;
026    import com.liferay.portal.kernel.search.Indexer;
027    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
028    import com.liferay.portal.kernel.search.QueryConfig;
029    import com.liferay.portal.kernel.search.SearchContext;
030    import com.liferay.portal.kernel.search.Sort;
031    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
032    import com.liferay.portal.kernel.util.CharPool;
033    import com.liferay.portal.kernel.util.ContentTypes;
034    import com.liferay.portal.kernel.util.FileUtil;
035    import com.liferay.portal.kernel.util.GetterUtil;
036    import com.liferay.portal.kernel.util.HtmlUtil;
037    import com.liferay.portal.kernel.util.HttpUtil;
038    import com.liferay.portal.kernel.util.ListUtil;
039    import com.liferay.portal.kernel.util.LocaleUtil;
040    import com.liferay.portal.kernel.util.LocalizationUtil;
041    import com.liferay.portal.kernel.util.MathUtil;
042    import com.liferay.portal.kernel.util.OrderByComparator;
043    import com.liferay.portal.kernel.util.PropsKeys;
044    import com.liferay.portal.kernel.util.StringPool;
045    import com.liferay.portal.kernel.util.StringUtil;
046    import com.liferay.portal.kernel.util.Time;
047    import com.liferay.portal.kernel.util.Validator;
048    import com.liferay.portal.kernel.workflow.WorkflowConstants;
049    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
050    import com.liferay.portal.kernel.xml.Document;
051    import com.liferay.portal.kernel.xml.DocumentException;
052    import com.liferay.portal.kernel.xml.Element;
053    import com.liferay.portal.kernel.xml.Node;
054    import com.liferay.portal.kernel.xml.SAXReaderUtil;
055    import com.liferay.portal.kernel.xml.XPath;
056    import com.liferay.portal.model.Company;
057    import com.liferay.portal.model.Group;
058    import com.liferay.portal.model.Image;
059    import com.liferay.portal.model.ModelHintsUtil;
060    import com.liferay.portal.model.ResourceConstants;
061    import com.liferay.portal.model.User;
062    import com.liferay.portal.service.ServiceContext;
063    import com.liferay.portal.service.ServiceContextUtil;
064    import com.liferay.portal.servlet.filters.cache.CacheUtil;
065    import com.liferay.portal.theme.ThemeDisplay;
066    import com.liferay.portal.util.PortalUtil;
067    import com.liferay.portal.util.PortletKeys;
068    import com.liferay.portal.util.PrefsPropsUtil;
069    import com.liferay.portal.util.PropsValues;
070    import com.liferay.portal.util.SubscriptionSender;
071    import com.liferay.portal.webserver.WebServerServletTokenUtil;
072    import com.liferay.portlet.asset.NoSuchEntryException;
073    import com.liferay.portlet.asset.model.AssetEntry;
074    import com.liferay.portlet.asset.model.AssetLink;
075    import com.liferay.portlet.asset.model.AssetLinkConstants;
076    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
077    import com.liferay.portlet.expando.model.ExpandoBridge;
078    import com.liferay.portlet.journal.ArticleContentException;
079    import com.liferay.portlet.journal.ArticleDisplayDateException;
080    import com.liferay.portlet.journal.ArticleExpirationDateException;
081    import com.liferay.portlet.journal.ArticleIdException;
082    import com.liferay.portlet.journal.ArticleReviewDateException;
083    import com.liferay.portlet.journal.ArticleSmallImageNameException;
084    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
085    import com.liferay.portlet.journal.ArticleTitleException;
086    import com.liferay.portlet.journal.ArticleTypeException;
087    import com.liferay.portlet.journal.ArticleVersionException;
088    import com.liferay.portlet.journal.DuplicateArticleIdException;
089    import com.liferay.portlet.journal.NoSuchArticleException;
090    import com.liferay.portlet.journal.NoSuchArticleResourceException;
091    import com.liferay.portlet.journal.NoSuchStructureException;
092    import com.liferay.portlet.journal.NoSuchTemplateException;
093    import com.liferay.portlet.journal.StructureXsdException;
094    import com.liferay.portlet.journal.model.JournalArticle;
095    import com.liferay.portlet.journal.model.JournalArticleConstants;
096    import com.liferay.portlet.journal.model.JournalArticleDisplay;
097    import com.liferay.portlet.journal.model.JournalArticleResource;
098    import com.liferay.portlet.journal.model.JournalStructure;
099    import com.liferay.portlet.journal.model.JournalTemplate;
100    import com.liferay.portlet.journal.model.impl.JournalArticleDisplayImpl;
101    import com.liferay.portlet.journal.service.base.JournalArticleLocalServiceBaseImpl;
102    import com.liferay.portlet.journal.util.JournalUtil;
103    import com.liferay.portlet.journal.util.comparator.ArticleIDComparator;
104    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
105    import com.liferay.portlet.journalcontent.util.JournalContentUtil;
106    
107    import java.io.File;
108    import java.io.IOException;
109    import java.io.Serializable;
110    
111    import java.util.Calendar;
112    import java.util.Date;
113    import java.util.HashMap;
114    import java.util.HashSet;
115    import java.util.LinkedHashMap;
116    import java.util.List;
117    import java.util.Locale;
118    import java.util.Map;
119    import java.util.Set;
120    
121    import javax.portlet.PortletPreferences;
122    
123    /**
124     * @author Brian Wing Shun Chan
125     * @author Raymond Augé
126     * @author Bruno Farache
127     * @author Juan Fernández
128     */
129    public class JournalArticleLocalServiceImpl
130            extends JournalArticleLocalServiceBaseImpl {
131    
132            public JournalArticle addArticle(
133                            long userId, long groupId, long classNameId, long classPK,
134                            String articleId, boolean autoArticleId, double version,
135                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
136                            String content, String type, String structureId, String templateId,
137                            String layoutUuid, int displayDateMonth, int displayDateDay,
138                            int displayDateYear, int displayDateHour, int displayDateMinute,
139                            int expirationDateMonth, int expirationDateDay,
140                            int expirationDateYear, int expirationDateHour,
141                            int expirationDateMinute, boolean neverExpire, int reviewDateMonth,
142                            int reviewDateDay, int reviewDateYear, int reviewDateHour,
143                            int reviewDateMinute, boolean neverReview, boolean indexable,
144                            boolean smallImage, String smallImageURL, File smallImageFile,
145                            Map<String, byte[]> images, String articleURL,
146                            ServiceContext serviceContext)
147                    throws PortalException, SystemException {
148    
149                    // Article
150    
151                    User user = userPersistence.findByPrimaryKey(userId);
152                    articleId = articleId.trim().toUpperCase();
153    
154                    Date displayDate = PortalUtil.getDate(
155                            displayDateMonth, displayDateDay, displayDateYear,
156                            displayDateHour, displayDateMinute, user.getTimeZone(),
157                            new ArticleDisplayDateException());
158    
159                    Date expirationDate = null;
160    
161                    if (!neverExpire) {
162                            expirationDate = PortalUtil.getDate(
163                                    expirationDateMonth, expirationDateDay, expirationDateYear,
164                                    expirationDateHour, expirationDateMinute, user.getTimeZone(),
165                                    new ArticleExpirationDateException());
166                    }
167    
168                    Date reviewDate = null;
169    
170                    if (!neverReview) {
171                            reviewDate = PortalUtil.getDate(
172                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
173                                    reviewDateMinute, user.getTimeZone(),
174                                    new ArticleReviewDateException());
175                    }
176    
177                    byte[] smallImageBytes = null;
178    
179                    try {
180                            smallImageBytes = FileUtil.getBytes(smallImageFile);
181                    }
182                    catch (IOException ioe) {
183                    }
184    
185                    Date now = new Date();
186    
187                    validate(
188                            user.getCompanyId(), groupId, classNameId, articleId, autoArticleId,
189                            version, titleMap, content, type, structureId, templateId,
190                            smallImage, smallImageURL, smallImageFile, smallImageBytes);
191    
192                    if (autoArticleId) {
193                            articleId = String.valueOf(counterLocalService.increment());
194                    }
195    
196                    long id = counterLocalService.increment();
197    
198                    long resourcePrimKey =
199                            journalArticleResourceLocalService.getArticleResourcePrimKey(
200                                    serviceContext.getUuid(), groupId, articleId);
201    
202                    JournalArticle article = journalArticlePersistence.create(id);
203    
204                    Locale locale = LocaleUtil.getDefault();
205    
206                    String defaultLanguageId = GetterUtil.getString(
207                            serviceContext.getAttribute("defaultLanguageId"));
208    
209                    if (Validator.isNotNull(defaultLanguageId)) {
210                            locale = LocaleUtil.fromLanguageId(defaultLanguageId);
211                    }
212    
213                    String title = titleMap.get(locale);
214    
215                    content = format(
216                            user, groupId, articleId, version, false, content, structureId,
217                            images);
218    
219                    article.setResourcePrimKey(resourcePrimKey);
220                    article.setGroupId(groupId);
221                    article.setCompanyId(user.getCompanyId());
222                    article.setUserId(user.getUserId());
223                    article.setUserName(user.getFullName());
224                    article.setCreateDate(serviceContext.getCreateDate(now));
225                    article.setModifiedDate(serviceContext.getModifiedDate(now));
226                    article.setClassNameId(classNameId);
227                    article.setClassPK(classPK);
228                    article.setArticleId(articleId);
229                    article.setVersion(version);
230                    article.setTitleMap(titleMap, locale);
231                    article.setUrlTitle(getUniqueUrlTitle(id, groupId, articleId, title));
232                    article.setDescriptionMap(descriptionMap, locale);
233                    article.setContent(content);
234                    article.setType(type);
235                    article.setStructureId(structureId);
236                    article.setTemplateId(templateId);
237                    article.setLayoutUuid(layoutUuid);
238                    article.setDisplayDate(displayDate);
239                    article.setExpirationDate(expirationDate);
240                    article.setReviewDate(reviewDate);
241                    article.setIndexable(indexable);
242                    article.setSmallImage(smallImage);
243                    article.setSmallImageId(counterLocalService.increment());
244                    article.setSmallImageURL(smallImageURL);
245    
246                    if ((expirationDate == null) || expirationDate.after(now)) {
247                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
248                    }
249                    else {
250                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
251                    }
252    
253                    journalArticlePersistence.update(article, false);
254    
255                    // Resources
256    
257                    if (serviceContext.getAddGroupPermissions() ||
258                            serviceContext.getAddGuestPermissions()) {
259    
260                            addArticleResources(
261                                    article, serviceContext.getAddGroupPermissions(),
262                                    serviceContext.getAddGuestPermissions());
263                    }
264                    else {
265                            addArticleResources(
266                                    article, serviceContext.getGroupPermissions(),
267                                    serviceContext.getGuestPermissions());
268                    }
269    
270                    // Expando
271    
272                    ExpandoBridge expandoBridge = article.getExpandoBridge();
273    
274                    expandoBridge.setAttributes(serviceContext);
275    
276                    // Small image
277    
278                    saveImages(
279                            smallImage, article.getSmallImageId(), smallImageFile,
280                            smallImageBytes);
281    
282                    // Asset
283    
284                    updateAsset(
285                            userId, article, serviceContext.getAssetCategoryIds(),
286                            serviceContext.getAssetTagNames(),
287                            serviceContext.getAssetLinkEntryIds());
288    
289                    // Message boards
290    
291                    if (PropsValues.JOURNAL_ARTICLE_COMMENTS_ENABLED) {
292                            mbMessageLocalService.addDiscussionMessage(
293                                    userId, article.getUserName(), groupId,
294                                    JournalArticle.class.getName(), resourcePrimKey,
295                                    WorkflowConstants.ACTION_PUBLISH);
296                    }
297    
298                    // Email
299    
300                    PortletPreferences preferences =
301                            ServiceContextUtil.getPortletPreferences(serviceContext);
302    
303                    sendEmail(article, articleURL, preferences, "requested");
304    
305                    // Workflow
306    
307                    if (classNameId == 0) {
308                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
309                                    user.getCompanyId(), groupId, userId,
310                                    JournalArticle.class.getName(), article.getId(), article,
311                                    serviceContext);
312    
313                            if (serviceContext.getWorkflowAction() !=
314                                            WorkflowConstants.ACTION_PUBLISH) {
315    
316                                    // Indexer
317    
318                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
319                                            JournalArticle.class);
320    
321                                    indexer.reindex(article);
322                            }
323                    }
324                    else {
325                            updateStatus(
326                                    userId, article, WorkflowConstants.STATUS_APPROVED, null,
327                                    serviceContext);
328                    }
329    
330                    return article;
331            }
332    
333            public void addArticleResources(
334                            JournalArticle article, boolean addGroupPermissions,
335                            boolean addGuestPermissions)
336                    throws PortalException, SystemException {
337    
338                    resourceLocalService.addResources(
339                            article.getCompanyId(), article.getGroupId(),
340                            article.getUserId(), JournalArticle.class.getName(),
341                            article.getResourcePrimKey(), false, addGroupPermissions,
342                            addGuestPermissions);
343            }
344    
345            public void addArticleResources(
346                            JournalArticle article, String[] groupPermissions,
347                            String[] guestPermissions)
348                    throws PortalException, SystemException {
349    
350                    resourceLocalService.addModelResources(
351                            article.getCompanyId(), article.getGroupId(),
352                            article.getUserId(), JournalArticle.class.getName(),
353                            article.getResourcePrimKey(), groupPermissions, guestPermissions);
354            }
355    
356            public void addArticleResources(
357                            long groupId, String articleId, boolean addGroupPermissions,
358                            boolean addGuestPermissions)
359                    throws PortalException, SystemException {
360    
361                    JournalArticle article = getLatestArticle(groupId, articleId);
362    
363                    addArticleResources(
364                            article, addGroupPermissions, addGuestPermissions);
365            }
366    
367            public void addArticleResources(
368                            long groupId, String articleId, String[] groupPermissions,
369                            String[] guestPermissions)
370                    throws PortalException, SystemException {
371    
372                    JournalArticle article = getLatestArticle(groupId, articleId);
373    
374                    addArticleResources(article, groupPermissions, guestPermissions);
375            }
376    
377            public JournalArticle checkArticleResourcePrimKey(
378                            long groupId, String articleId, double version)
379                    throws PortalException, SystemException {
380    
381                    JournalArticle article = journalArticlePersistence.findByG_A_V(
382                            groupId, articleId, version);
383    
384                    if (article.getResourcePrimKey() > 0) {
385                            return article;
386                    }
387    
388                    long resourcePrimKey =
389                            journalArticleResourceLocalService.getArticleResourcePrimKey(
390                                    groupId, articleId);
391    
392                    article.setResourcePrimKey(resourcePrimKey);
393    
394                    journalArticlePersistence.update(article, false);
395    
396                    return article;
397            }
398    
399            public void checkArticles() throws PortalException, SystemException {
400                    Date now = new Date();
401    
402                    List<JournalArticle> articles =
403                            journalArticleFinder.findByExpirationDate(
404                                    0, WorkflowConstants.STATUS_APPROVED, now);
405    
406                    if (_log.isDebugEnabled()) {
407                            _log.debug("Expiring " + articles.size() + " articles");
408                    }
409    
410                    Set<Long> companyIds = new HashSet<Long>();
411    
412                    for (JournalArticle article : articles) {
413                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
414    
415                            journalArticlePersistence.update(article, false);
416    
417                            if (article.isIndexable()) {
418                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
419                                            JournalArticle.class);
420    
421                                    indexer.delete(article);
422                            }
423    
424                            updatePreviousApprovedArticle(article);
425    
426                            JournalContentUtil.clearCache(
427                                    article.getGroupId(), article.getArticleId(),
428                                    article.getTemplateId());
429    
430                            companyIds.add(article.getCompanyId());
431                    }
432    
433                    for (long companyId : companyIds) {
434                            CacheUtil.clearCache(companyId);
435                    }
436    
437                    articles = journalArticleFinder.findByReviewDate(
438                            0, now, new Date(now.getTime() - _JOURNAL_ARTICLE_CHECK_INTERVAL));
439    
440                    if (_log.isDebugEnabled()) {
441                            _log.debug(
442                                    "Sending review notifications for " + articles.size() +
443                                            " articles");
444                    }
445    
446                    for (JournalArticle article : articles) {
447                            String articleURL = StringPool.BLANK;
448    
449                            long ownerId = article.getGroupId();
450                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
451                            long plid = PortletKeys.PREFS_PLID_SHARED;
452                            String portletId = PortletKeys.JOURNAL;
453    
454                            PortletPreferences preferences =
455                                    portletPreferencesLocalService.getPreferences(
456                                            article.getCompanyId(), ownerId, ownerType, plid,
457                                            portletId);
458    
459                            sendEmail(article, articleURL, preferences, "review");
460                    }
461            }
462    
463            public void checkNewLine(long groupId, String articleId, double version)
464                    throws PortalException, SystemException {
465    
466                    JournalArticle article = journalArticlePersistence.findByG_A_V(
467                            groupId, articleId, version);
468    
469                    String content = GetterUtil.getString(article.getContent());
470    
471                    if (content.indexOf("\\n") != -1) {
472                            content = StringUtil.replace(
473                                    content,
474                                    new String[] {"\\n", "\\r"},
475                                    new String[] {"\n", "\r"});
476    
477                            article.setContent(content);
478    
479                            journalArticlePersistence.update(article, false);
480                    }
481            }
482    
483            public void checkStructure(long groupId, String articleId, double version)
484                    throws PortalException, SystemException {
485    
486                    JournalArticle article = journalArticlePersistence.findByG_A_V(
487                            groupId, articleId, version);
488    
489                    if (Validator.isNull(article.getStructureId())) {
490                            return;
491                    }
492    
493                    try {
494                            checkStructure(article);
495                    }
496                    catch (DocumentException de) {
497                            _log.error(de, de);
498                    }
499            }
500    
501            public JournalArticle copyArticle(
502                            long userId, long groupId, String oldArticleId, String newArticleId,
503                            boolean autoArticleId, double version)
504                    throws PortalException, SystemException {
505    
506                    // Article
507    
508                    User user = userPersistence.findByPrimaryKey(userId);
509                    oldArticleId = oldArticleId.trim().toUpperCase();
510                    newArticleId = newArticleId.trim().toUpperCase();
511                    Date now = new Date();
512    
513                    JournalArticle oldArticle = journalArticlePersistence.findByG_A_V(
514                            groupId, oldArticleId, version);
515    
516                    if (autoArticleId) {
517                            newArticleId = String.valueOf(counterLocalService.increment());
518                    }
519                    else {
520                            validate(groupId, newArticleId);
521                    }
522    
523                    long id = counterLocalService.increment();
524    
525                    long resourcePrimKey =
526                            journalArticleResourceLocalService.getArticleResourcePrimKey(
527                                    groupId, newArticleId);
528    
529                    JournalArticle newArticle = journalArticlePersistence.create(id);
530    
531                    newArticle.setResourcePrimKey(resourcePrimKey);
532                    newArticle.setGroupId(groupId);
533                    newArticle.setCompanyId(user.getCompanyId());
534                    newArticle.setUserId(user.getUserId());
535                    newArticle.setUserName(user.getFullName());
536                    newArticle.setCreateDate(now);
537                    newArticle.setModifiedDate(now);
538                    newArticle.setArticleId(newArticleId);
539                    newArticle.setVersion(JournalArticleConstants.VERSION_DEFAULT);
540                    newArticle.setTitle(oldArticle.getTitle());
541                    newArticle.setDescription(oldArticle.getDescription());
542    
543                    try {
544                            copyArticleImages(oldArticle, newArticle);
545                    }
546                    catch (Exception e) {
547                            newArticle.setContent(oldArticle.getContent());
548                    }
549    
550                    newArticle.setType(oldArticle.getType());
551                    newArticle.setStructureId(oldArticle.getStructureId());
552                    newArticle.setTemplateId(oldArticle.getTemplateId());
553                    newArticle.setLayoutUuid(oldArticle.getLayoutUuid());
554                    newArticle.setDisplayDate(oldArticle.getDisplayDate());
555                    newArticle.setExpirationDate(oldArticle.getExpirationDate());
556                    newArticle.setReviewDate(oldArticle.getReviewDate());
557                    newArticle.setIndexable(oldArticle.isIndexable());
558                    newArticle.setSmallImage(oldArticle.isSmallImage());
559                    newArticle.setSmallImageId(counterLocalService.increment());
560                    newArticle.setSmallImageURL(oldArticle.getSmallImageURL());
561                    newArticle.setStatus(oldArticle.getStatus());
562    
563                    journalArticlePersistence.update(newArticle, false);
564    
565                    // Resources
566    
567                    addArticleResources(newArticle, true, true);
568    
569                    // Small image
570    
571                    if (oldArticle.getSmallImage()) {
572                            Image image = imageLocalService.getImage(
573                                    oldArticle.getSmallImageId());
574    
575                            byte[] smallImageBytes = image.getTextObj();
576    
577                            imageLocalService.updateImage(
578                                    newArticle.getSmallImageId(), smallImageBytes);
579                    }
580    
581                    // Asset
582    
583                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
584                            JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
585                    String[] assetTagNames = assetTagLocalService.getTagNames(
586                            JournalArticle.class.getName(), oldArticle.getResourcePrimKey());
587    
588                    updateAsset(userId, newArticle, assetCategoryIds, assetTagNames, null);
589    
590                    return newArticle;
591            }
592    
593            public void deleteArticle(
594                            JournalArticle article, String articleURL,
595                            ServiceContext serviceContext)
596                    throws PortalException, SystemException {
597    
598                    if (article.isApproved() &&
599                            isLatestVersion(
600                                    article.getGroupId(), article.getArticleId(),
601                                    article.getVersion(), WorkflowConstants.STATUS_APPROVED)) {
602    
603                            updatePreviousApprovedArticle(article);
604                    }
605    
606                    // Email
607    
608                    PortletPreferences preferences =
609                            ServiceContextUtil.getPortletPreferences(serviceContext);
610    
611                    if ((preferences != null) && !article.isApproved() &&
612                            isLatestVersion(
613                                    article.getGroupId(), article.getArticleId(),
614                                    article.getVersion())) {
615    
616                            sendEmail(article, articleURL, preferences, "denied");
617                    }
618    
619                    // Images
620    
621                    journalArticleImageLocalService.deleteImages(
622                            article.getGroupId(), article.getArticleId(), article.getVersion());
623    
624                    // Workflow
625    
626                    if (!article.isDraft()) {
627                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
628                                    article.getCompanyId(), article.getGroupId(),
629                                    JournalArticle.class.getName(), article.getId());
630                    }
631    
632                    int articlesCount = journalArticlePersistence.countByG_A(
633                            article.getGroupId(), article.getArticleId());
634    
635                    if (articlesCount == 1) {
636    
637                            // Ratings
638    
639                            ratingsStatsLocalService.deleteStats(
640                                    JournalArticle.class.getName(), article.getResourcePrimKey());
641    
642                            // Message boards
643    
644                            mbMessageLocalService.deleteDiscussionMessages(
645                                    JournalArticle.class.getName(), article.getResourcePrimKey());
646    
647                            // Asset
648    
649                            assetEntryLocalService.deleteEntry(
650                                    JournalArticle.class.getName(), article.getResourcePrimKey());
651    
652                            // Content searches
653    
654                            journalContentSearchLocalService.deleteArticleContentSearches(
655                                    article.getGroupId(), article.getArticleId());
656    
657                            // Small image
658    
659                            imageLocalService.deleteImage(article.getSmallImageId());
660    
661                            // Expando
662    
663                            expandoValueLocalService.deleteValues(
664                                    JournalArticle.class.getName(), article.getResourcePrimKey());
665    
666                            // Resources
667    
668                            resourceLocalService.deleteResource(
669                                    article.getCompanyId(), JournalArticle.class.getName(),
670                                    ResourceConstants.SCOPE_INDIVIDUAL,
671                                    article.getResourcePrimKey());
672    
673                            // Resource
674    
675                            try {
676                                    journalArticleResourceLocalService.deleteArticleResource(
677                                            article.getGroupId(), article.getArticleId());
678                            }
679                            catch (NoSuchArticleResourceException nsare) {
680                            }
681                    }
682    
683                    // Article
684    
685                    journalArticlePersistence.remove(article);
686            }
687    
688            public void deleteArticle(
689                            long groupId, String articleId, double version, String articleURL,
690                            ServiceContext serviceContext)
691                    throws PortalException, SystemException {
692    
693                    JournalArticle article = journalArticlePersistence.findByG_A_V(
694                            groupId, articleId, version);
695    
696                    deleteArticle(article, articleURL, serviceContext);
697            }
698    
699            public void deleteArticle(
700                            long groupId, String articleId, ServiceContext serviceContext)
701                    throws PortalException, SystemException {
702    
703                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
704                            groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
705                            new ArticleVersionComparator(true));
706    
707                    for (JournalArticle article : articles) {
708                            deleteArticle(article, null, serviceContext);
709                    }
710            }
711    
712            public void deleteArticles(long groupId)
713                    throws PortalException, SystemException {
714    
715                    for (JournalArticle article :
716                                    journalArticlePersistence.findByGroupId(groupId)) {
717    
718                            deleteArticle(article, null, null);
719                    }
720            }
721    
722            public void deleteLayoutArticleReferences(long groupId, String layoutUuid)
723                    throws SystemException {
724    
725                    List<JournalArticle> articles = journalArticlePersistence.findByG_L(
726                            groupId, layoutUuid);
727    
728                    for (JournalArticle article: articles) {
729                            article.setLayoutUuid(StringPool.BLANK);
730    
731                            journalArticlePersistence.update(article, false);
732                    }
733            }
734    
735            public JournalArticle expireArticle(
736                            long userId, long groupId, String articleId, double version,
737                            String articleURL, ServiceContext serviceContext)
738                    throws PortalException, SystemException {
739    
740                    return updateStatus(
741                            userId, groupId, articleId, version,
742                            WorkflowConstants.STATUS_EXPIRED, articleURL, serviceContext);
743            }
744    
745            public void expireArticle(
746                            long userId, long groupId, String articleId, String articleURL,
747                            ServiceContext serviceContext)
748                    throws PortalException, SystemException {
749    
750                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
751                            groupId, articleId, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
752                            new ArticleVersionComparator(true));
753    
754                    for (JournalArticle article : articles) {
755                            expireArticle(
756                                    userId, groupId, article.getArticleId(), article.getVersion(),
757                                    articleURL, serviceContext);
758                    }
759            }
760    
761            public JournalArticle getArticle(long id)
762                    throws PortalException, SystemException {
763    
764                    return journalArticlePersistence.findByPrimaryKey(id);
765            }
766    
767            public JournalArticle getArticle(long groupId, String articleId)
768                    throws PortalException, SystemException {
769    
770                    // Get the latest article that is approved, if none are approved, get
771                    // the latest unapproved article
772    
773                    try {
774                            return getLatestArticle(
775                                    groupId, articleId, WorkflowConstants.STATUS_APPROVED);
776                    }
777                    catch (NoSuchArticleException nsae) {
778                            return getLatestArticle(
779                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
780                    }
781            }
782    
783            public JournalArticle getArticle(
784                            long groupId, String articleId, double version)
785                    throws PortalException, SystemException {
786    
787                    return journalArticlePersistence.findByG_A_V(
788                            groupId, articleId, version);
789            }
790    
791            public JournalArticle getArticle(
792                            long groupId, String className, long classPK)
793                    throws PortalException, SystemException {
794    
795                    long classNameId = PortalUtil.getClassNameId(className);
796    
797                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
798                            groupId, classNameId, classPK);
799    
800                    if (articles.isEmpty()) {
801                            throw new NoSuchArticleException(
802                                    "No approved JournalArticle with the key {groupId=" + groupId +
803                                            ", className=" + className + ", classPK=" + classPK + "}");
804                    }
805    
806                    return articles.get(0);
807            }
808    
809            public JournalArticle getArticleByUrlTitle(long groupId, String urlTitle)
810                    throws PortalException, SystemException {
811    
812                    // Get the latest article that is approved, if none are approved, get
813                    // the latest unapproved article
814    
815                    try {
816                            return getLatestArticleByUrlTitle(
817                                    groupId, urlTitle, WorkflowConstants.STATUS_APPROVED);
818                    }
819                    catch (NoSuchArticleException nsae) {
820                            return getLatestArticleByUrlTitle(
821                                    groupId, urlTitle, WorkflowConstants.STATUS_PENDING);
822                    }
823            }
824    
825            public String getArticleContent(
826                            JournalArticle article, String templateId, String viewMode,
827                            String languageId, ThemeDisplay themeDisplay)
828                    throws PortalException, SystemException {
829    
830                    JournalArticleDisplay articleDisplay = getArticleDisplay(
831                            article, templateId, viewMode, languageId, 1, null, themeDisplay);
832    
833                    if (articleDisplay == null) {
834                            return StringPool.BLANK;
835                    }
836                    else {
837                            return articleDisplay.getContent();
838                    }
839            }
840    
841            public String getArticleContent(
842                            long groupId, String articleId, double version, String viewMode,
843                            String templateId, String languageId, ThemeDisplay themeDisplay)
844                    throws PortalException, SystemException {
845    
846                    JournalArticleDisplay articleDisplay = getArticleDisplay(
847                            groupId, articleId, version, templateId, viewMode, languageId,
848                            themeDisplay);
849    
850                    if (articleDisplay == null) {
851                            return StringPool.BLANK;
852                    }
853                    else {
854                            return articleDisplay.getContent();
855                    }
856            }
857    
858            public String getArticleContent(
859                            long groupId, String articleId, double version, String viewMode,
860                            String languageId, ThemeDisplay themeDisplay)
861                    throws PortalException, SystemException {
862    
863                    return getArticleContent(
864                            groupId, articleId, version, viewMode, null, languageId,
865                            themeDisplay);
866            }
867    
868            public String getArticleContent(
869                            long groupId, String articleId, String viewMode, String templateId,
870                            String languageId, ThemeDisplay themeDisplay)
871                    throws PortalException, SystemException {
872    
873                    JournalArticleDisplay articleDisplay = getArticleDisplay(
874                            groupId, articleId, templateId, viewMode, languageId, themeDisplay);
875    
876                    return articleDisplay.getContent();
877            }
878    
879            public String getArticleContent(
880                            long groupId, String articleId, String viewMode, String languageId,
881                            ThemeDisplay themeDisplay)
882                    throws PortalException, SystemException {
883    
884                    return getArticleContent(
885                            groupId, articleId, viewMode, null, languageId, themeDisplay);
886            }
887    
888            public JournalArticleDisplay getArticleDisplay(
889                            JournalArticle article, String templateId, String viewMode,
890                            String languageId, int page, String xmlRequest,
891                            ThemeDisplay themeDisplay)
892                    throws PortalException, SystemException {
893    
894                    String content = null;
895    
896                    if (page < 1) {
897                            page = 1;
898                    }
899    
900                    int numberOfPages = 1;
901                    boolean paginate = false;
902                    boolean pageFlow = false;
903    
904                    boolean cacheable = true;
905    
906                    if (Validator.isNull(xmlRequest)) {
907                            xmlRequest = "<request />";
908                    }
909    
910                    Map<String, String> tokens = JournalUtil.getTokens(
911                            article.getGroupId(), themeDisplay, xmlRequest);
912    
913                    tokens.put(
914                            "article_resource_pk",
915                            String.valueOf(article.getResourcePrimKey()));
916    
917                    String defaultTemplateId = article.getTemplateId();
918    
919                    if (article.isTemplateDriven()) {
920                            if (Validator.isNull(templateId)) {
921                                    templateId = defaultTemplateId;
922                            }
923    
924                            tokens.put("structure_id", article.getStructureId());
925                            tokens.put("template_id", templateId);
926                    }
927    
928                    String xml = article.getContent();
929    
930                    try {
931                            Document document = null;
932    
933                            Element rootElement = null;
934    
935                            if (article.isTemplateDriven()) {
936                                    document = SAXReaderUtil.read(xml);
937    
938                                    rootElement = document.getRootElement();
939    
940                                    Document requestDocument = SAXReaderUtil.read(xmlRequest);
941    
942                                    List<Element> pages = rootElement.elements("page");
943    
944                                    if (!pages.isEmpty()) {
945                                            pageFlow = true;
946    
947                                            String targetPage = requestDocument.valueOf(
948                                                    "/request/parameters/parameter[name='targetPage']/" +
949                                                            "value");
950    
951                                            Element pageElement = null;
952    
953                                            if (Validator.isNotNull(targetPage)) {
954                                                    XPath xpathSelector = SAXReaderUtil.createXPath(
955                                                            "/root/page[@id = '" + targetPage + "']");
956    
957                                                    pageElement = (Element)xpathSelector.selectSingleNode(
958                                                            document);
959                                            }
960    
961                                            if (pageElement != null) {
962                                                    document = SAXReaderUtil.createDocument(pageElement);
963    
964                                                    rootElement = document.getRootElement();
965    
966                                                    numberOfPages = pages.size();
967                                            }
968                                            else {
969                                                    if (page > pages.size()) {
970                                                            page = 1;
971                                                    }
972    
973                                                    pageElement = pages.get(page - 1);
974    
975                                                    document = SAXReaderUtil.createDocument(pageElement);
976    
977                                                    rootElement = document.getRootElement();
978    
979                                                    numberOfPages = pages.size();
980                                                    paginate = true;
981                                            }
982                                    }
983    
984                                    rootElement.add(requestDocument.getRootElement().createCopy());
985    
986                                    JournalUtil.addAllReservedEls(rootElement, tokens, article);
987    
988                                    xml = DDMXMLUtil.formatXML(document);
989                            }
990                    }
991                    catch (DocumentException de) {
992                            throw new SystemException(de);
993                    }
994                    catch (IOException ioe) {
995                            throw new SystemException(ioe);
996                    }
997    
998                    try {
999                            if (_log.isDebugEnabled()) {
1000                                    _log.debug(
1001                                            "Transforming " + article.getArticleId() + " " +
1002                                                    article.getVersion() + " " + languageId);
1003                            }
1004    
1005                            String script = null;
1006                            String langType = null;
1007    
1008                            if (article.isTemplateDriven()) {
1009    
1010                                    // Try with specified template first (in the current group and
1011                                    // the global group). If a template is not specified, use the
1012                                    // default one. If the specified template does not exit, use the
1013                                    // default one. If the default one does not exist, throw an
1014                                    // exception.
1015    
1016                                    JournalTemplate template = null;
1017    
1018                                    try {
1019                                            template = journalTemplatePersistence.findByG_T(
1020                                                    article.getGroupId(), templateId);
1021                                    }
1022                                    catch (NoSuchTemplateException nste1) {
1023                                            try {
1024                                                    Group companyGroup = groupLocalService.getCompanyGroup(
1025                                                            article.getCompanyId());
1026    
1027                                                    template = journalTemplatePersistence.findByG_T(
1028                                                            companyGroup.getGroupId(), templateId);
1029    
1030                                                    tokens.put(
1031                                                            "company_group_id",
1032                                                            String.valueOf(companyGroup.getGroupId()));
1033                                            }
1034                                            catch (NoSuchTemplateException nste2) {
1035                                                    if (!defaultTemplateId.equals(templateId)) {
1036                                                            template = journalTemplatePersistence.findByG_T(
1037                                                                    article.getGroupId(), defaultTemplateId);
1038                                                    }
1039                                                    else {
1040                                                            throw nste1;
1041                                                    }
1042                                            }
1043                                    }
1044    
1045                                    script = template.getXsl();
1046                                    langType = template.getLangType();
1047                                    cacheable = template.isCacheable();
1048                            }
1049    
1050                            content = JournalUtil.transform(
1051                                    themeDisplay, tokens, viewMode, languageId, xml, script,
1052                                    langType);
1053    
1054                            if (!pageFlow) {
1055                                    String[] pieces = StringUtil.split(
1056                                            content, PropsValues.JOURNAL_ARTICLE_TOKEN_PAGE_BREAK);
1057    
1058                                    if (pieces.length > 1) {
1059                                            if (page > pieces.length) {
1060                                                    page = 1;
1061                                            }
1062    
1063                                            content = pieces[page - 1];
1064                                            numberOfPages = pieces.length;
1065                                            paginate = true;
1066                                    }
1067                            }
1068                    }
1069                    catch (Exception e) {
1070                            throw new SystemException(e);
1071                    }
1072    
1073                    return new JournalArticleDisplayImpl(
1074                            article.getCompanyId(), article.getId(),
1075                            article.getResourcePrimKey(), article.getGroupId(),
1076                            article.getUserId(), article.getArticleId(), article.getVersion(),
1077                            article.getTitle(languageId), article.getUrlTitle(),
1078                            article.getDescription(languageId), article.getAvailableLocales(),
1079                            content, article.getType(), article.getStructureId(), templateId,
1080                            article.isSmallImage(), article.getSmallImageId(),
1081                            article.getSmallImageURL(), numberOfPages, page, paginate,
1082                            cacheable);
1083            }
1084    
1085            public JournalArticleDisplay getArticleDisplay(
1086                            long groupId, String articleId, double version, String templateId,
1087                            String viewMode, String languageId, int page, String xmlRequest,
1088                            ThemeDisplay themeDisplay)
1089                    throws PortalException, SystemException {
1090    
1091                    Date now = new Date();
1092    
1093                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1094                            groupId, articleId, version);
1095    
1096                    if (article.isExpired()) {
1097                            Date expirationDate = article.getExpirationDate();
1098    
1099                            if ((expirationDate != null) && expirationDate.before(now)) {
1100                                    return null;
1101                            }
1102                    }
1103    
1104                    if (article.getDisplayDate().after(now)) {
1105                            return null;
1106                    }
1107    
1108                    return getArticleDisplay(
1109                            article, templateId, viewMode, languageId, page, xmlRequest,
1110                            themeDisplay);
1111            }
1112    
1113            public JournalArticleDisplay getArticleDisplay(
1114                            long groupId, String articleId, double version, String templateId,
1115                            String viewMode, String languageId, ThemeDisplay themeDisplay)
1116                    throws PortalException, SystemException {
1117    
1118                    return getArticleDisplay(
1119                            groupId, articleId, version, templateId, viewMode, languageId, 1,
1120                            null, themeDisplay);
1121            }
1122    
1123            public JournalArticleDisplay getArticleDisplay(
1124                            long groupId, String articleId, String viewMode, String languageId,
1125                            int page, String xmlRequest, ThemeDisplay themeDisplay)
1126                    throws PortalException, SystemException {
1127    
1128                    return getArticleDisplay(
1129                            groupId, articleId, null, viewMode, languageId, page, xmlRequest,
1130                            themeDisplay);
1131            }
1132    
1133            public JournalArticleDisplay getArticleDisplay(
1134                            long groupId, String articleId, String templateId, String viewMode,
1135                            String languageId, int page, String xmlRequest,
1136                            ThemeDisplay themeDisplay)
1137                    throws PortalException, SystemException {
1138    
1139                    JournalArticle article = getDisplayArticle(groupId, articleId);
1140    
1141                    return getArticleDisplay(
1142                            groupId, articleId, article.getVersion(), templateId, viewMode,
1143                            languageId, page, xmlRequest, themeDisplay);
1144            }
1145    
1146            public JournalArticleDisplay getArticleDisplay(
1147                            long groupId, String articleId, String templateId, String viewMode,
1148                            String languageId, ThemeDisplay themeDisplay)
1149                    throws PortalException, SystemException {
1150    
1151                    JournalArticle article = getDisplayArticle(groupId, articleId);
1152    
1153                    return getArticleDisplay(
1154                            groupId, articleId, article.getVersion(), templateId, viewMode,
1155                            languageId, themeDisplay);
1156            }
1157    
1158            public JournalArticleDisplay getArticleDisplay(
1159                            long groupId, String articleId, String viewMode, String languageId,
1160                            ThemeDisplay themeDisplay)
1161                    throws PortalException, SystemException {
1162    
1163                    return getArticleDisplay(
1164                            groupId, articleId, null, viewMode, languageId, themeDisplay);
1165            }
1166    
1167            public List<JournalArticle> getArticles() throws SystemException {
1168                    return journalArticlePersistence.findAll();
1169            }
1170    
1171            public List<JournalArticle> getArticles(long groupId)
1172                    throws SystemException {
1173    
1174                    return journalArticlePersistence.findByGroupId(groupId);
1175            }
1176    
1177            public List<JournalArticle> getArticles(long groupId, int start, int end)
1178                    throws SystemException {
1179    
1180                    return journalArticlePersistence.findByGroupId(groupId, start, end);
1181            }
1182    
1183            public List<JournalArticle> getArticles(
1184                            long groupId, int start, int end, OrderByComparator obc)
1185                    throws SystemException {
1186    
1187                    return journalArticlePersistence.findByGroupId(
1188                            groupId, start, end, obc);
1189            }
1190    
1191            public List<JournalArticle> getArticles(long groupId, String articleId)
1192                    throws SystemException {
1193    
1194                    return journalArticlePersistence.findByG_A(groupId, articleId);
1195            }
1196    
1197            public List<JournalArticle> getArticlesBySmallImageId(long smallImageId)
1198                    throws SystemException {
1199    
1200                    return journalArticlePersistence.findBySmallImageId(smallImageId);
1201            }
1202    
1203            public int getArticlesCount(long groupId) throws SystemException {
1204                    return journalArticlePersistence.countByGroupId(groupId);
1205            }
1206    
1207            public List<JournalArticle> getCompanyArticles(
1208                            long companyId, double version, int status, int start, int end)
1209                    throws SystemException {
1210    
1211                    if (status == WorkflowConstants.STATUS_ANY) {
1212                            return journalArticlePersistence.findByC_V(
1213                                    companyId, version, start, end, new ArticleIDComparator(true));
1214                    }
1215                    else {
1216                            return journalArticlePersistence.findByC_V_ST(
1217                                    companyId, version, status, start, end,
1218                                    new ArticleIDComparator(true));
1219                    }
1220            }
1221    
1222            public List<JournalArticle> getCompanyArticles(
1223                            long companyId, int status, int start, int end)
1224                    throws SystemException {
1225    
1226                    if (status == WorkflowConstants.STATUS_ANY) {
1227                            return journalArticlePersistence.findByCompanyId(
1228                                    companyId, start, end, new ArticleIDComparator(true));
1229                    }
1230                    else {
1231                            return journalArticlePersistence.findByC_ST(
1232                                    companyId, status, start, end, new ArticleIDComparator(true));
1233                    }
1234            }
1235    
1236            public int getCompanyArticlesCount(
1237                            long companyId, double version, int status, int start, int end)
1238                    throws SystemException {
1239    
1240                    if (status == WorkflowConstants.STATUS_ANY) {
1241                            return journalArticlePersistence.countByC_V(companyId, version);
1242                    }
1243                    else {
1244                            return journalArticlePersistence.countByC_V_ST(
1245                                    companyId, version, status);
1246                    }
1247            }
1248    
1249            public int getCompanyArticlesCount(long companyId, int status)
1250                    throws SystemException {
1251    
1252                    if (status == WorkflowConstants.STATUS_ANY) {
1253                            return journalArticlePersistence.countByCompanyId(companyId);
1254                    }
1255                    else {
1256                            return journalArticlePersistence.countByC_ST(companyId, status);
1257                    }
1258            }
1259    
1260            public JournalArticle getDisplayArticle(long groupId, String articleId)
1261                    throws PortalException, SystemException {
1262    
1263                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
1264                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
1265    
1266                    if (articles.isEmpty()) {
1267                            throw new NoSuchArticleException(
1268                                    "No approved JournalArticle with the key {groupId=" + groupId +
1269                                            ", " + "articleId=" + articleId + "}");
1270    
1271                    }
1272    
1273                    Date now = new Date();
1274    
1275                    for (int i = 0; i < articles.size(); i++) {
1276                            JournalArticle article = articles.get(i);
1277    
1278                            Date expirationDate = article.getExpirationDate();
1279    
1280                            if (article.getDisplayDate().before(now) &&
1281                                    ((expirationDate == null) || expirationDate.after(now))) {
1282    
1283                                    return article;
1284                            }
1285                    }
1286    
1287                    return articles.get(0);
1288            }
1289    
1290            public JournalArticle getLatestArticle(long resourcePrimKey)
1291                    throws PortalException, SystemException {
1292    
1293                    return getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
1294            }
1295    
1296            public JournalArticle getLatestArticle(long resourcePrimKey, int status)
1297                    throws PortalException, SystemException {
1298    
1299                    return getLatestArticle(resourcePrimKey, status, true);
1300            }
1301    
1302            public JournalArticle getLatestArticle(
1303                            long resourcePrimKey, int status, boolean preferApproved)
1304                    throws PortalException, SystemException {
1305    
1306                    List<JournalArticle> articles = null;
1307    
1308                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1309    
1310                    if (status == WorkflowConstants.STATUS_ANY) {
1311                            if (preferApproved) {
1312                                    articles = journalArticlePersistence.findByR_ST(
1313                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED, 0, 1,
1314                                            orderByComparator);
1315                            }
1316    
1317                            if ((articles == null) || (articles.size() == 0)) {
1318                                    articles = journalArticlePersistence.findByResourcePrimKey(
1319                                            resourcePrimKey, 0, 1, orderByComparator);
1320                            }
1321                    }
1322                    else {
1323                            articles = journalArticlePersistence.findByR_ST(
1324                                    resourcePrimKey, status, 0, 1, orderByComparator);
1325                    }
1326    
1327                    if (articles.isEmpty()) {
1328                            throw new NoSuchArticleException(
1329                                    "No JournalArticle with the key {resourcePrimKey=" +
1330                                            resourcePrimKey + "}");
1331                    }
1332    
1333                    return articles.get(0);
1334            }
1335    
1336            public JournalArticle getLatestArticle(long groupId, String articleId)
1337                    throws PortalException, SystemException {
1338    
1339                    return getLatestArticle(
1340                            groupId, articleId, WorkflowConstants.STATUS_ANY);
1341            }
1342    
1343            public JournalArticle getLatestArticle(
1344                            long groupId, String articleId, int status)
1345                    throws PortalException, SystemException {
1346    
1347                    List<JournalArticle> articles = null;
1348    
1349                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1350    
1351                    if (status == WorkflowConstants.STATUS_ANY) {
1352                            articles = journalArticlePersistence.findByG_A(
1353                                    groupId, articleId, 0, 1, orderByComparator);
1354                    }
1355                    else {
1356                            articles = journalArticlePersistence.findByG_A_ST(
1357                                    groupId, articleId, status, 0, 1, orderByComparator);
1358                    }
1359    
1360                    if (articles.isEmpty()) {
1361                            throw new NoSuchArticleException(
1362                                    "No JournalArticle with the key {groupId=" + groupId +
1363                                            ", articleId=" + articleId + ", status=" + status + "}");
1364                    }
1365    
1366                    return articles.get(0);
1367            }
1368    
1369            public JournalArticle getLatestArticle(
1370                            long groupId, String className, long classPK)
1371                    throws PortalException, SystemException {
1372    
1373                    long classNameId = PortalUtil.getClassNameId(className);
1374    
1375                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_C(
1376                            groupId, classNameId, classPK, 0, 1,
1377                            new ArticleVersionComparator());
1378    
1379                    if (articles.isEmpty()) {
1380                            throw new NoSuchArticleException(
1381                                    "No JournalArticle with the key {groupId=" + groupId +
1382                                            ", className=" + className + ", classPK =" + classPK + "}");
1383                    }
1384    
1385                    return articles.get(0);
1386            }
1387    
1388            public JournalArticle getLatestArticleByUrlTitle(
1389                            long groupId, String urlTitle, int status)
1390                    throws PortalException, SystemException {
1391    
1392                    List<JournalArticle> articles = null;
1393    
1394                    OrderByComparator orderByComparator = new ArticleVersionComparator();
1395    
1396                    if (status == WorkflowConstants.STATUS_ANY) {
1397                            articles = journalArticlePersistence.findByG_UT(
1398                                    groupId, urlTitle, 0, 1, orderByComparator);
1399                    }
1400                    else {
1401                            articles = journalArticlePersistence.findByG_UT_ST(
1402                                    groupId, urlTitle, status, 0, 1, orderByComparator);
1403                    }
1404    
1405                    if (articles.isEmpty()) {
1406                            throw new NoSuchArticleException(
1407                                    "No JournalArticle with the key {groupId=" + groupId +
1408                                            ", urlTitle=" + urlTitle + ", status=" + status + "}");
1409                    }
1410    
1411                    return articles.get(0);
1412            }
1413    
1414            public double getLatestVersion(long groupId, String articleId)
1415                    throws PortalException, SystemException {
1416    
1417                    JournalArticle article = getLatestArticle(groupId, articleId);
1418    
1419                    return article.getVersion();
1420            }
1421    
1422            public double getLatestVersion(
1423                            long groupId, String articleId, int status)
1424                    throws PortalException, SystemException {
1425    
1426                    JournalArticle article = getLatestArticle(groupId, articleId, status);
1427    
1428                    return article.getVersion();
1429            }
1430    
1431            public List<JournalArticle> getStructureArticles(
1432                            long groupId, String structureId)
1433                    throws SystemException {
1434    
1435                    return journalArticlePersistence.findByG_S(groupId, structureId);
1436            }
1437    
1438            public List<JournalArticle> getStructureArticles(
1439                            long groupId, String structureId, int start, int end,
1440                            OrderByComparator obc)
1441                    throws SystemException {
1442    
1443                    return journalArticlePersistence.findByG_S(
1444                            groupId, structureId, start, end, obc);
1445            }
1446    
1447            public int getStructureArticlesCount(long groupId, String structureId)
1448                    throws SystemException {
1449    
1450                    return journalArticlePersistence.countByG_S(groupId, structureId);
1451            }
1452    
1453            public List<JournalArticle> getTemplateArticles(
1454                            long groupId, String templateId)
1455                    throws SystemException {
1456    
1457                    return journalArticlePersistence.findByG_T(groupId, templateId);
1458            }
1459    
1460            public List<JournalArticle> getTemplateArticles(
1461                            long groupId, String templateId, int start, int end,
1462                            OrderByComparator obc)
1463                    throws SystemException {
1464    
1465                    return journalArticlePersistence.findByG_T(
1466                            groupId, templateId, start, end, obc);
1467            }
1468    
1469            public int getTemplateArticlesCount(long groupId, String templateId)
1470                    throws SystemException {
1471    
1472                    return journalArticlePersistence.countByG_T(groupId, templateId);
1473            }
1474    
1475            public boolean hasArticle(long groupId, String articleId)
1476                    throws SystemException {
1477    
1478                    try {
1479                            getArticle(groupId, articleId);
1480    
1481                            return true;
1482                    }
1483                    catch (PortalException pe) {
1484                            return false;
1485                    }
1486            }
1487    
1488            public boolean isLatestVersion(
1489                            long groupId, String articleId, double version)
1490                    throws PortalException, SystemException {
1491    
1492                    if (getLatestVersion(groupId, articleId) == version) {
1493                            return true;
1494                    }
1495                    else {
1496                            return false;
1497                    }
1498            }
1499    
1500            public boolean isLatestVersion(
1501                            long groupId, String articleId, double version, int status)
1502                    throws PortalException, SystemException {
1503    
1504                    if (getLatestVersion(groupId, articleId, status) == version) {
1505                            return true;
1506                    }
1507                    else {
1508                            return false;
1509                    }
1510            }
1511    
1512            public JournalArticle removeArticleLocale(
1513                            long groupId, String articleId, double version, String languageId)
1514                    throws PortalException, SystemException {
1515    
1516                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1517                            groupId, articleId, version);
1518    
1519                    String title = article.getTitle();
1520    
1521                    title = LocalizationUtil.removeLocalization(
1522                            title, "static-content", languageId, true);
1523    
1524                    article.setTitle(title);
1525    
1526                    String description = article.getDescription();
1527    
1528                    description = LocalizationUtil.removeLocalization(
1529                            description, "static-content", languageId, true);
1530    
1531                    article.setDescription(description);
1532    
1533                    String content = article.getContent();
1534    
1535                    if (article.isTemplateDriven()) {
1536                            content = JournalUtil.removeArticleLocale(content, languageId);
1537                    }
1538                    else {
1539                            content = LocalizationUtil.removeLocalization(
1540                                    content, "static-content", languageId, true);
1541                    }
1542    
1543                    article.setContent(content);
1544    
1545                    journalArticlePersistence.update(article, false);
1546    
1547                    return article;
1548            }
1549    
1550            public List<JournalArticle> search(
1551                            long companyId, long groupId, long classNameId, String keywords,
1552                            Double version, String type, String structureId, String templateId,
1553                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1554                            int start, int end, OrderByComparator obc)
1555                    throws SystemException {
1556    
1557                    return journalArticleFinder.findByKeywords(
1558                            companyId, groupId, classNameId, keywords, version, type,
1559                            structureId, templateId, displayDateGT, displayDateLT, status,
1560                            reviewDate, start, end, obc);
1561            }
1562    
1563            public List<JournalArticle> search(
1564                            long companyId, long groupId, long classNameId, String articleId,
1565                            Double version, String title, String description, String content,
1566                            String type, String structureId, String templateId,
1567                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1568                            boolean andOperator, int start, int end, OrderByComparator obc)
1569                    throws SystemException {
1570    
1571                    return journalArticleFinder.findByC_G_C_A_V_T_D_C_T_S_T_D_S_R(
1572                            companyId, groupId, classNameId, articleId, version, title,
1573                            description, content, type, structureId, templateId, displayDateGT,
1574                            displayDateLT, status, reviewDate, andOperator, start, end, obc);
1575            }
1576    
1577            public List<JournalArticle> search(
1578                            long companyId, long groupId, long classNameId, String articleId,
1579                            Double version, String title, String description, String content,
1580                            String type, String[] structureIds, String[] templateIds,
1581                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1582                            boolean andOperator, int start, int end, OrderByComparator obc)
1583                    throws SystemException {
1584    
1585                    return journalArticleFinder.findByC_G_C_A_V_T_D_C_T_S_T_D_S_R(
1586                            companyId, groupId, classNameId, articleId, version, title,
1587                            description, content, type, structureIds, templateIds,
1588                            displayDateGT, displayDateLT, status, reviewDate, andOperator,
1589                            start, end, obc);
1590            }
1591    
1592            public Hits search(
1593                            long companyId, long groupId, long classNameId, String structureId,
1594                            String templateId, String keywords,
1595                            LinkedHashMap<String, Object> params, int start, int end, Sort sort)
1596                    throws SystemException {
1597    
1598                    String articleId = null;
1599                    String title = null;
1600                    String description = null;
1601                    String content = null;
1602                    boolean andOperator = false;
1603    
1604                    if (Validator.isNotNull(keywords)) {
1605                            articleId = keywords;
1606                            title = keywords;
1607                            description = keywords;
1608                            content = keywords;
1609                    }
1610                    else {
1611                            andOperator = true;
1612                    }
1613    
1614                    String status = String.valueOf(WorkflowConstants.STATUS_ANY);
1615    
1616                    return search(
1617                            companyId, groupId, classNameId, articleId, title, description,
1618                            content, null, status, structureId, templateId, params, andOperator,
1619                            start, end, sort);
1620            }
1621    
1622            public Hits search(
1623                            long companyId, long groupId, long classNameId, String articleId,
1624                            String title, String description, String content, String type,
1625                            String status, String structureId, String templateId,
1626                            LinkedHashMap<String, Object> params, boolean andSearch, int start,
1627                            int end, Sort sort)
1628                    throws SystemException {
1629    
1630                    try {
1631                            Map<String, Serializable> attributes =
1632                                    new HashMap<String, Serializable>();
1633    
1634                            attributes.put(Field.CLASS_NAME_ID, classNameId);
1635                            attributes.put(Field.CONTENT, content);
1636                            attributes.put(Field.DESCRIPTION, description);
1637                            attributes.put(Field.STATUS, status);
1638                            attributes.put(Field.TITLE, title);
1639                            attributes.put(Field.TYPE, type);
1640                            attributes.put("articleId", articleId);
1641                            attributes.put("params", params);
1642                            attributes.put("structureId", structureId);
1643                            attributes.put("templateId", templateId);
1644    
1645                            SearchContext searchContext = new SearchContext();
1646    
1647                            searchContext.setAndSearch(andSearch);
1648                            searchContext.setAttributes(attributes);
1649                            searchContext.setCompanyId(companyId);
1650                            searchContext.setGroupIds(new long[] {groupId});
1651                            searchContext.setEnd(end);
1652                            searchContext.setSorts(new Sort[] {sort});
1653    
1654                            QueryConfig queryConfig = new QueryConfig();
1655    
1656                            queryConfig.setHighlightEnabled(false);
1657                            queryConfig.setScoreEnabled(false);
1658    
1659                            searchContext.setQueryConfig(queryConfig);
1660    
1661                            searchContext.setStart(start);
1662    
1663                            Indexer indexer = IndexerRegistryUtil.getIndexer(
1664                                    JournalArticle.class);
1665    
1666                            return indexer.search(searchContext);
1667                    }
1668                    catch (Exception e) {
1669                            throw new SystemException(e);
1670                    }
1671            }
1672    
1673            public int searchCount(
1674                            long companyId, long groupId, long classNameId, String keywords,
1675                            Double version, String type, String structureId, String templateId,
1676                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate)
1677                    throws SystemException {
1678    
1679                    return journalArticleFinder.countByKeywords(
1680                            companyId, groupId, classNameId, keywords, version, type,
1681                            structureId, templateId, displayDateGT, displayDateLT, status,
1682                            reviewDate);
1683            }
1684    
1685            public int searchCount(
1686                            long companyId, long groupId, long classNameId, String articleId,
1687                            Double version, String title, String description, String content,
1688                            String type, String structureId, String templateId,
1689                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1690                            boolean andOperator)
1691                    throws SystemException {
1692    
1693                    return journalArticleFinder.countByC_G_C_A_V_T_D_C_T_S_T_D_S_R(
1694                            companyId, groupId, classNameId, articleId, version, title,
1695                            description, content, type, structureId, templateId, displayDateGT,
1696                            displayDateLT, status, reviewDate, andOperator);
1697            }
1698    
1699            public int searchCount(
1700                            long companyId, long groupId, long classNameId, String articleId,
1701                            Double version, String title, String description, String content,
1702                            String type, String[] structureIds, String[] templateIds,
1703                            Date displayDateGT, Date displayDateLT, int status, Date reviewDate,
1704                            boolean andOperator)
1705                    throws SystemException {
1706    
1707                    return journalArticleFinder.countByC_G_C_A_V_T_D_C_T_S_T_D_S_R(
1708                            companyId, groupId, classNameId, articleId, version, title,
1709                            description, content, type, structureIds, templateIds,
1710                            displayDateGT, displayDateLT, status, reviewDate, andOperator);
1711            }
1712    
1713            public void subscribe(long userId, long groupId)
1714                    throws PortalException, SystemException {
1715    
1716                    subscriptionLocalService.addSubscription(
1717                            userId, groupId, JournalArticle.class.getName(), groupId);
1718            }
1719    
1720            public void unsubscribe(long userId, long groupId)
1721                    throws PortalException, SystemException {
1722    
1723                    subscriptionLocalService.deleteSubscription(
1724                            userId, JournalArticle.class.getName(), groupId);
1725            }
1726    
1727            public JournalArticle updateArticle(
1728                            long userId, long groupId, String articleId, double version,
1729                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
1730                            String content, String layoutUuid, ServiceContext serviceContext)
1731                    throws PortalException, SystemException {
1732    
1733                    User user = userPersistence.findByPrimaryKey(userId);
1734    
1735                    JournalArticle article = journalArticlePersistence.findByG_A_V(
1736                            groupId, articleId, version);
1737    
1738                    Date displayDate = article.getDisplayDate();
1739    
1740                    int displayDateMonth = 0;
1741                    int displayDateDay = 0;
1742                    int displayDateYear = 0;
1743                    int displayDateHour = 0;
1744                    int displayDateMinute = 0;
1745    
1746                    if (displayDate != null) {
1747                            Calendar displayCal = CalendarFactoryUtil.getCalendar(
1748                                    user.getTimeZone());
1749    
1750                            displayCal.setTime(displayDate);
1751    
1752                            displayDateMonth = displayCal.get(Calendar.MONTH);
1753                            displayDateDay = displayCal.get(Calendar.DATE);
1754                            displayDateYear = displayCal.get(Calendar.YEAR);
1755                            displayDateHour = displayCal.get(Calendar.HOUR);
1756                            displayDateMinute = displayCal.get(Calendar.MINUTE);
1757    
1758                            if (displayCal.get(Calendar.AM_PM) == Calendar.PM) {
1759                                    displayDateHour += 12;
1760                            }
1761                    }
1762    
1763                    Date expirationDate = article.getExpirationDate();
1764    
1765                    int expirationDateMonth = 0;
1766                    int expirationDateDay = 0;
1767                    int expirationDateYear = 0;
1768                    int expirationDateHour = 0;
1769                    int expirationDateMinute = 0;
1770                    boolean neverExpire = true;
1771    
1772                    if (expirationDate != null) {
1773                            Calendar expirationCal = CalendarFactoryUtil.getCalendar(
1774                                    user.getTimeZone());
1775    
1776                            expirationCal.setTime(expirationDate);
1777    
1778                            expirationDateMonth = expirationCal.get(Calendar.MONTH);
1779                            expirationDateDay = expirationCal.get(Calendar.DATE);
1780                            expirationDateYear = expirationCal.get(Calendar.YEAR);
1781                            expirationDateHour = expirationCal.get(Calendar.HOUR);
1782                            expirationDateMinute = expirationCal.get(Calendar.MINUTE);
1783                            neverExpire = false;
1784    
1785                            if (expirationCal.get(Calendar.AM_PM) == Calendar.PM) {
1786                                    expirationDateHour += 12;
1787                            }
1788                    }
1789    
1790                    Date reviewDate = article.getReviewDate();
1791    
1792                    int reviewDateMonth = 0;
1793                    int reviewDateDay = 0;
1794                    int reviewDateYear = 0;
1795                    int reviewDateHour = 0;
1796                    int reviewDateMinute = 0;
1797                    boolean neverReview = true;
1798    
1799                    if (reviewDate != null) {
1800                            Calendar reviewCal = CalendarFactoryUtil.getCalendar(
1801                                    user.getTimeZone());
1802    
1803                            reviewCal.setTime(reviewDate);
1804    
1805                            reviewDateMonth = reviewCal.get(Calendar.MONTH);
1806                            reviewDateDay = reviewCal.get(Calendar.DATE);
1807                            reviewDateYear = reviewCal.get(Calendar.YEAR);
1808                            reviewDateHour = reviewCal.get(Calendar.HOUR);
1809                            reviewDateMinute = reviewCal.get(Calendar.MINUTE);
1810                            neverReview = false;
1811    
1812                            if (reviewCal.get(Calendar.AM_PM) == Calendar.PM) {
1813                                    reviewDateHour += 12;
1814                            }
1815                    }
1816    
1817                    return updateArticle(
1818                            userId, groupId, articleId, version, titleMap, descriptionMap,
1819                            content, article.getType(), article.getStructureId(),
1820                            article.getTemplateId(), layoutUuid, displayDateMonth,
1821                            displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
1822                            expirationDateMonth, expirationDateDay, expirationDateYear,
1823                            expirationDateHour, expirationDateMinute, neverExpire,
1824                            reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1825                            reviewDateMinute, neverReview, article.getIndexable(),
1826                            article.isSmallImage(), article.getSmallImageURL(), null, null,
1827                            null, serviceContext);
1828            }
1829    
1830            public JournalArticle updateArticle(
1831                            long userId, long groupId, String articleId, double version,
1832                            Map<Locale, String> titleMap, Map<Locale, String> descriptionMap,
1833                            String content, String type, String structureId, String templateId,
1834                            String layoutUuid, int displayDateMonth, int displayDateDay,
1835                            int displayDateYear, int displayDateHour, int displayDateMinute,
1836                            int expirationDateMonth, int expirationDateDay,
1837                            int expirationDateYear, int expirationDateHour,
1838                            int expirationDateMinute, boolean neverExpire, int reviewDateMonth,
1839                            int reviewDateDay, int reviewDateYear, int reviewDateHour,
1840                            int reviewDateMinute, boolean neverReview, boolean indexable,
1841                            boolean smallImage, String smallImageURL, File smallImageFile,
1842                            Map<String, byte[]> images, String articleURL,
1843                            ServiceContext serviceContext)
1844                    throws PortalException, SystemException {
1845    
1846                    // Article
1847    
1848                    User user = userPersistence.findByPrimaryKey(userId);
1849                    articleId = articleId.trim().toUpperCase();
1850    
1851                    Date displayDate = PortalUtil.getDate(
1852                            displayDateMonth, displayDateDay, displayDateYear,
1853                            displayDateHour, displayDateMinute, user.getTimeZone(),
1854                            new ArticleDisplayDateException());
1855    
1856                    Date expirationDate = null;
1857    
1858                    if (!neverExpire) {
1859                            expirationDate = PortalUtil.getDate(
1860                                    expirationDateMonth, expirationDateDay, expirationDateYear,
1861                                    expirationDateHour, expirationDateMinute, user.getTimeZone(),
1862                                    new ArticleExpirationDateException());
1863                    }
1864    
1865                    Date now = new Date();
1866    
1867                    boolean expired = false;
1868    
1869                    if ((expirationDate != null) && expirationDate.before(now)) {
1870                            expired = true;
1871                    }
1872    
1873                    Date reviewDate = null;
1874    
1875                    if (!neverReview) {
1876                            reviewDate = PortalUtil.getDate(
1877                                    reviewDateMonth, reviewDateDay, reviewDateYear, reviewDateHour,
1878                                    reviewDateMinute, user.getTimeZone(),
1879                                    new ArticleReviewDateException());
1880                    }
1881    
1882                    byte[] smallImageBytes = null;
1883    
1884                    try {
1885                            smallImageBytes = FileUtil.getBytes(smallImageFile);
1886                    }
1887                    catch (IOException ioe) {
1888                    }
1889    
1890                    validate(
1891                            user.getCompanyId(), groupId, -1, titleMap, content, type,
1892                            structureId, templateId, smallImage, smallImageURL, smallImageFile,
1893                            smallImageBytes);
1894    
1895                    JournalArticle oldArticle = null;
1896                    double oldVersion = 0;
1897    
1898                    boolean incrementVersion = false;
1899    
1900                    boolean imported = GetterUtil.getBoolean(
1901                            serviceContext.getAttribute("imported"));
1902    
1903                    if (imported) {
1904                            oldArticle = getArticle(groupId, articleId, version);
1905                            oldVersion = version;
1906    
1907                            if (!expired) {
1908                                    incrementVersion = true;
1909                            }
1910                            else {
1911                                    return expireArticle(
1912                                            userId, groupId, articleId, version, articleURL,
1913                                            serviceContext);
1914                            }
1915                    }
1916                    else {
1917                            oldArticle = getLatestArticle(
1918                                    groupId, articleId, WorkflowConstants.STATUS_ANY);
1919    
1920                            oldVersion = oldArticle.getVersion();
1921    
1922                            if ((version > 0) && (version != oldVersion)) {
1923                                    throw new ArticleVersionException();
1924                            }
1925    
1926                            if (oldArticle.isApproved() || oldArticle.isExpired()) {
1927                                    incrementVersion = true;
1928                            }
1929                    }
1930    
1931                    JournalArticle article = null;
1932    
1933                    if (incrementVersion) {
1934                            double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
1935    
1936                            long id = counterLocalService.increment();
1937    
1938                            article = journalArticlePersistence.create(id);
1939    
1940                            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
1941                            article.setGroupId(oldArticle.getGroupId());
1942                            article.setCompanyId(oldArticle.getCompanyId());
1943                            article.setUserId(oldArticle.getUserId());
1944                            article.setUserName(oldArticle.getUserName());
1945                            article.setCreateDate(serviceContext.getModifiedDate(now));
1946                            article.setClassNameId(oldArticle.getClassNameId());
1947                            article.setClassPK(oldArticle.getClassPK());
1948                            article.setArticleId(articleId);
1949                            article.setVersion(newVersion);
1950                            article.setSmallImageId(oldArticle.getSmallImageId());
1951                    }
1952                    else {
1953                            article = oldArticle;
1954                    }
1955    
1956                    Locale locale = LocaleUtil.getDefault();
1957    
1958                    String defaultLanguageId = GetterUtil.getString(
1959                            serviceContext.getAttribute("defaultLanguageId"));
1960    
1961                    if (Validator.isNotNull(defaultLanguageId)) {
1962                            locale = LocaleUtil.fromLanguageId(defaultLanguageId);
1963                    }
1964    
1965                    String title = titleMap.get(locale);
1966    
1967                    content = format(
1968                            user, groupId, articleId, article.getVersion(), incrementVersion,
1969                            content, structureId, images);
1970    
1971                    article.setModifiedDate(serviceContext.getModifiedDate(now));
1972                    article.setTitleMap(titleMap, locale);
1973                    article.setUrlTitle(
1974                            getUniqueUrlTitle(article.getId(), groupId, articleId, title));
1975                    article.setDescriptionMap(descriptionMap, locale);
1976                    article.setContent(content);
1977                    article.setType(type);
1978                    article.setStructureId(structureId);
1979                    article.setTemplateId(templateId);
1980                    article.setLayoutUuid(layoutUuid);
1981                    article.setDisplayDate(displayDate);
1982                    article.setExpirationDate(expirationDate);
1983                    article.setReviewDate(reviewDate);
1984                    article.setIndexable(indexable);
1985                    article.setSmallImage(smallImage);
1986    
1987                    if (article.getSmallImageId() == 0) {
1988                            article.setSmallImageId(counterLocalService.increment());
1989                    }
1990    
1991                    article.setSmallImageURL(smallImageURL);
1992    
1993                    if (oldArticle.isPending()) {
1994                            article.setStatus(oldArticle.getStatus());
1995                    }
1996                    else if (!expired) {
1997                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
1998                    }
1999                    else {
2000                            article.setStatus(WorkflowConstants.STATUS_EXPIRED);
2001                    }
2002    
2003                    journalArticlePersistence.update(article, false);
2004    
2005                    // Asset
2006    
2007                    updateAsset(
2008                            userId, article, serviceContext.getAssetCategoryIds(),
2009                            serviceContext.getAssetTagNames(),
2010                            serviceContext.getAssetLinkEntryIds());
2011    
2012                    // Expando
2013    
2014                    ExpandoBridge expandoBridge = article.getExpandoBridge();
2015    
2016                    expandoBridge.setAttributes(serviceContext);
2017    
2018                    // Small image
2019    
2020                    saveImages(
2021                            smallImage, article.getSmallImageId(), smallImageFile,
2022                            smallImageBytes);
2023    
2024                    // Email
2025    
2026                    PortletPreferences preferences =
2027                            ServiceContextUtil.getPortletPreferences(serviceContext);
2028    
2029                    // Workflow
2030    
2031                    if (serviceContext.getWorkflowAction() ==
2032                                    WorkflowConstants.ACTION_PUBLISH) {
2033    
2034                            sendEmail(article, articleURL, preferences, "requested");
2035    
2036                            WorkflowHandlerRegistryUtil.startWorkflowInstance(
2037                                    user.getCompanyId(), groupId, userId,
2038                                    JournalArticle.class.getName(), article.getId(),
2039                                    article, serviceContext);
2040                    }
2041                    else if (article.getVersion() ==
2042                                            JournalArticleConstants.VERSION_DEFAULT) {
2043    
2044                            // Indexer
2045    
2046                            Indexer indexer = IndexerRegistryUtil.getIndexer(
2047                                    JournalArticle.class);
2048    
2049                            indexer.reindex(article);
2050                    }
2051    
2052                    return article;
2053            }
2054    
2055            public JournalArticle updateArticle(
2056                            long userId, long groupId, String articleId, double version,
2057                            String content, ServiceContext serviceContext)
2058                    throws PortalException, SystemException {
2059    
2060                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2061                            groupId, articleId, version);
2062    
2063                    return updateArticle(
2064                            userId, groupId, articleId, version, article.getTitleMap(),
2065                            article.getDescriptionMap(), content, article.getLayoutUuid(),
2066                            serviceContext);
2067            }
2068    
2069            public JournalArticle updateArticleTranslation(
2070                            long groupId, String articleId, double version, Locale locale,
2071                            String title, String description, String content)
2072                    throws PortalException, SystemException {
2073    
2074                    validateContent(content);
2075    
2076                    JournalArticle oldArticle = getLatestArticle(
2077                            groupId, articleId, WorkflowConstants.STATUS_ANY);
2078    
2079                    double oldVersion = oldArticle.getVersion();
2080    
2081                    if ((version > 0) && (version != oldVersion)) {
2082                            throw new ArticleVersionException();
2083                    }
2084    
2085                    JournalArticle article = null;
2086    
2087                    if (!oldArticle.isDraft()) {
2088                            double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
2089    
2090                            long id = counterLocalService.increment();
2091    
2092                            article = journalArticlePersistence.create(id);
2093    
2094                            User user = userService.getUserById(oldArticle.getUserId());
2095    
2096                            article.setResourcePrimKey(oldArticle.getResourcePrimKey());
2097                            article.setGroupId(oldArticle.getGroupId());
2098                            article.setCompanyId(oldArticle.getCompanyId());
2099                            article.setUserId(oldArticle.getUserId());
2100                            article.setUserName(user.getFullName());
2101                            article.setCreateDate(new Date());
2102                            article.setModifiedDate(new Date());
2103                            article.setClassNameId(oldArticle.getClassNameId());
2104                            article.setClassPK(oldArticle.getClassPK());
2105                            article.setArticleId(articleId);
2106                            article.setVersion(newVersion);
2107                            article.setTitleMap(oldArticle.getTitleMap());
2108                            article.setUrlTitle(
2109                                    getUniqueUrlTitle(article.getId(), groupId, articleId, title));
2110                            article.setDescriptionMap(oldArticle.getDescriptionMap());
2111                            article.setType(oldArticle.getType());
2112                            article.setStructureId(oldArticle.getStructureId());
2113                            article.setTemplateId(oldArticle.getTemplateId());
2114                            article.setLayoutUuid(oldArticle.getLayoutUuid());
2115                            article.setDisplayDate(oldArticle.getDisplayDate());
2116                            article.setExpirationDate(oldArticle.getExpirationDate());
2117                            article.setReviewDate(oldArticle.getReviewDate());
2118                            article.setIndexable(oldArticle.getIndexable());
2119                            article.setSmallImage(oldArticle.getSmallImage());
2120                            article.setSmallImageId(oldArticle.getSmallImageId());
2121    
2122                            if (article.getSmallImageId() == 0) {
2123                                    article.setSmallImageId(counterLocalService.increment());
2124                            }
2125    
2126                            article.setSmallImageURL(oldArticle.getSmallImageURL());
2127    
2128                            article.setStatus(WorkflowConstants.STATUS_DRAFT);
2129                            article.setStatusDate(new Date());
2130                    }
2131                    else {
2132                            article = oldArticle;
2133                    }
2134    
2135                    Map<Locale, String> titleMap = article.getTitleMap();
2136    
2137                    titleMap.put(locale, title);
2138    
2139                    article.setTitleMap(titleMap);
2140    
2141                    Map<Locale, String> descriptionMap = article.getDescriptionMap();
2142    
2143                    descriptionMap.put(locale, description);
2144    
2145                    article.setDescriptionMap(descriptionMap);
2146    
2147                    article.setContent(content);
2148    
2149                    journalArticlePersistence.update(article, false);
2150    
2151                    return article;
2152            }
2153    
2154            public void updateAsset(
2155                            long userId, JournalArticle article, long[] assetCategoryIds,
2156                            String[] assetTagNames, long[] assetLinkEntryIds)
2157                    throws PortalException, SystemException {
2158    
2159                    // Get the earliest display date and latest expiration date among
2160                    // all article versions
2161    
2162                    Date[] dateInterval = getDateInterval(
2163                            article.getGroupId(), article.getArticleId(),
2164                            article.getDisplayDate(), article.getExpirationDate());
2165    
2166                    Date displayDate = dateInterval[0];
2167                    Date expirationDate = dateInterval[1];
2168    
2169                    boolean visible = article.isApproved();
2170    
2171                    if (article.getClassNameId() > 0) {
2172                            visible = false;
2173                    }
2174    
2175                    boolean addDraftAssetEntry = false;
2176    
2177                    if (!article.isApproved() &&
2178                            (article.getVersion() != JournalArticleConstants.VERSION_DEFAULT)) {
2179    
2180                            int approvedArticlesCount =
2181                                    journalArticlePersistence.countByG_A_ST(
2182                                            article.getGroupId(), article.getArticleId(),
2183                                            WorkflowConstants.STATUS_APPROVED);
2184    
2185                            if (approvedArticlesCount > 0) {
2186                                    addDraftAssetEntry = true;
2187                            }
2188                    }
2189    
2190                    AssetEntry assetEntry = null;
2191    
2192                    if (addDraftAssetEntry) {
2193                            assetEntry = assetEntryLocalService.updateEntry(
2194                                    userId, article.getGroupId(), JournalArticle.class.getName(),
2195                                    article.getPrimaryKey(), article.getUuid(),
2196                                    getClassTypeId(article), assetCategoryIds, assetTagNames, false,
2197                                    null, null, displayDate, expirationDate, ContentTypes.TEXT_HTML,
2198                                    article.getTitle(), article.getDescription(),
2199                                    article.getDescription(), null, article.getLayoutUuid(), 0, 0,
2200                                    null, false);
2201                    }
2202                    else {
2203                            JournalArticleResource journalArticleResource =
2204                                    journalArticleResourceLocalService.getArticleResource(
2205                                            article.getResourcePrimKey());
2206    
2207                            assetEntry = assetEntryLocalService.updateEntry(
2208                                    userId, article.getGroupId(), JournalArticle.class.getName(),
2209                                    journalArticleResource.getResourcePrimKey(),
2210                                    journalArticleResource.getUuid(), getClassTypeId(article),
2211                                    assetCategoryIds, assetTagNames, visible, null, null,
2212                                    displayDate, expirationDate, ContentTypes.TEXT_HTML,
2213                                    article.getTitle(), article.getDescription(),
2214                                    article.getDescription(), null, article.getLayoutUuid(), 0, 0,
2215                                    null, false);
2216                    }
2217    
2218                    assetLinkLocalService.updateLinks(
2219                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
2220                            AssetLinkConstants.TYPE_RELATED);
2221            }
2222    
2223            public JournalArticle updateContent(
2224                            long groupId, String articleId, double version, String content)
2225                    throws PortalException, SystemException {
2226    
2227                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2228                            groupId, articleId, version);
2229    
2230                    article.setContent(content);
2231    
2232                    journalArticlePersistence.update(article, false);
2233    
2234                    return article;
2235            }
2236    
2237            public JournalArticle updateStatus(
2238                            long userId, JournalArticle article, int status, String articleURL,
2239                            ServiceContext serviceContext)
2240                    throws PortalException, SystemException {
2241    
2242                    // Article
2243    
2244                    User user = userPersistence.findByPrimaryKey(userId);
2245                    Date now = new Date();
2246    
2247                    int oldStatus = article.getStatus();
2248    
2249                    article.setModifiedDate(serviceContext.getModifiedDate(now));
2250    
2251                    boolean neverExpire = false;
2252    
2253                    if (status == WorkflowConstants.STATUS_APPROVED) {
2254                            Date expirationDate = article.getExpirationDate();
2255    
2256                            if ((expirationDate != null) && expirationDate.before(now)) {
2257                                    neverExpire = true;
2258    
2259                                    article.setExpirationDate(null);
2260                            }
2261                    }
2262    
2263                    if (status == WorkflowConstants.STATUS_EXPIRED) {
2264                            article.setExpirationDate(now);
2265                    }
2266    
2267                    article.setStatus(status);
2268                    article.setStatusByUserId(user.getUserId());
2269                    article.setStatusByUserName(user.getFullName());
2270                    article.setStatusDate(serviceContext.getModifiedDate(now));
2271    
2272                    journalArticlePersistence.update(article, false);
2273    
2274                    if (isLatestVersion(
2275                                    article.getGroupId(), article.getArticleId(),
2276                                    article.getVersion())) {
2277    
2278                            if (status == WorkflowConstants.STATUS_APPROVED) {
2279                                    updateUrlTitles(
2280                                            article.getGroupId(), article.getArticleId(),
2281                                            article.getUrlTitle());
2282    
2283                                    // Asset
2284    
2285                                    if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2286                                            (article.getVersion() !=
2287                                                    JournalArticleConstants.VERSION_DEFAULT)) {
2288    
2289                                            AssetEntry draftAssetEntry = null;
2290    
2291                                            try {
2292                                                    draftAssetEntry = assetEntryLocalService.getEntry(
2293                                                            JournalArticle.class.getName(),
2294                                                            article.getPrimaryKey());
2295    
2296                                                    Date[] dateInterval = getDateInterval(
2297                                                            article.getGroupId(), article.getArticleId(),
2298                                                            article.getDisplayDate(),
2299                                                            article.getExpirationDate());
2300    
2301                                                    Date displayDate = dateInterval[0];
2302                                                    Date expirationDate = dateInterval[1];
2303    
2304                                                    long[] assetCategoryIds =
2305                                                            draftAssetEntry.getCategoryIds();
2306                                                    String[] assetTagNames = draftAssetEntry.getTagNames();
2307    
2308                                                    List<AssetLink> assetLinks =
2309                                                            assetLinkLocalService.getDirectLinks(
2310                                                                    draftAssetEntry.getEntryId(),
2311                                                                    AssetLinkConstants.TYPE_RELATED);
2312    
2313                                                    long[] assetLinkEntryIds = StringUtil.split(
2314                                                            ListUtil.toString(
2315                                                                    assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2316    
2317                                                    boolean visible = true;
2318    
2319                                                    if (article.getClassNameId() > 0) {
2320                                                            visible = false;
2321                                                    }
2322    
2323                                                    AssetEntry assetEntry =
2324                                                            assetEntryLocalService.updateEntry(
2325                                                                    userId, article.getGroupId(),
2326                                                                    JournalArticle.class.getName(),
2327                                                                    article.getResourcePrimKey(), article.getUuid(),
2328                                                                    getClassTypeId(article), assetCategoryIds,
2329                                                                    assetTagNames, visible, null, null, displayDate,
2330                                                                    expirationDate, ContentTypes.TEXT_HTML,
2331                                                                    article.getTitle(), article.getDescription(),
2332                                                                    article.getDescription(), null,
2333                                                                    article.getLayoutUuid(), 0, 0, null, false);
2334    
2335                                                    assetLinkLocalService.updateLinks(
2336                                                            userId, assetEntry.getEntryId(),
2337                                                            assetLinkEntryIds, AssetLinkConstants.TYPE_RELATED);
2338    
2339                                                    assetEntryLocalService.deleteEntry(
2340                                                            JournalArticle.class.getName(),
2341                                                            article.getPrimaryKey());
2342                                            }
2343                                            catch (NoSuchEntryException nsee) {
2344                                            }
2345                                    }
2346    
2347                                    if (article.getClassNameId() == 0) {
2348                                            AssetEntry assetEntry =
2349                                                    assetEntryLocalService.updateVisible(
2350                                                            JournalArticle.class.getName(),
2351                                                            article.getResourcePrimKey(), true);
2352    
2353                                            if (neverExpire) {
2354                                                    assetEntry.setExpirationDate(null);
2355    
2356                                                    assetEntryLocalService.updateAssetEntry(
2357                                                            assetEntry, false);
2358                                            }
2359                                    }
2360    
2361                                    // Expando
2362    
2363                                    ExpandoBridge expandoBridge = article.getExpandoBridge();
2364    
2365                                    expandoBridge.setAttributes(serviceContext);
2366    
2367                                    // Indexer
2368    
2369                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
2370                                            JournalArticle.class);
2371    
2372                                    indexer.reindex(article);
2373                            }
2374                            else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
2375                                    updatePreviousApprovedArticle(article);
2376                            }
2377                    }
2378    
2379                    if (article.getClassNameId() == 0) {
2380    
2381                            // Email
2382    
2383                            if ((oldStatus == WorkflowConstants.STATUS_PENDING) &&
2384                                    ((status == WorkflowConstants.STATUS_APPROVED) ||
2385                                     (status == WorkflowConstants.STATUS_DENIED))) {
2386    
2387                                    String msg = "granted";
2388    
2389                                    if (status == WorkflowConstants.STATUS_DENIED) {
2390                                            msg = "denied";
2391                                    }
2392    
2393                                    try {
2394                                            PortletPreferences preferences =
2395                                                    ServiceContextUtil.getPortletPreferences(
2396                                                            serviceContext);
2397    
2398                                            sendEmail(article, articleURL, preferences, msg);
2399                                    }
2400                                    catch (Exception e) {
2401                                            _log.error(
2402                                                    "Unable to send email to notify the change of status " +
2403                                                            " to " + msg + " for article " + article.getId() +
2404                                                                    ": " + e.getMessage());
2405                                    }
2406                            }
2407    
2408                            // Subscriptions
2409    
2410                            notifySubscribers(article, serviceContext);
2411                    }
2412    
2413                    return article;
2414            }
2415    
2416            public JournalArticle updateStatus(
2417                            long userId, long classPK, int status,
2418                            ServiceContext serviceContext)
2419                    throws PortalException, SystemException {
2420    
2421                    JournalArticle article = getArticle(classPK);
2422    
2423                    return updateStatus(userId, article, status, null, serviceContext);
2424            }
2425    
2426            public JournalArticle updateStatus(
2427                            long userId, long groupId, String articleId, double version,
2428                            int status, String articleURL, ServiceContext serviceContext)
2429                    throws PortalException, SystemException {
2430    
2431                    JournalArticle article = journalArticlePersistence.findByG_A_V(
2432                            groupId, articleId, version);
2433    
2434                    return updateStatus(
2435                            userId, article, status, articleURL, serviceContext);
2436            }
2437    
2438            public void updateTemplateId(
2439                            long groupId, long classNameId, String oldTemplateId,
2440                            String newTemplateId)
2441                    throws SystemException {
2442    
2443                    List<JournalArticle> articles = journalArticlePersistence.findByG_C_T(
2444                            groupId, classNameId, oldTemplateId);
2445    
2446                    for (JournalArticle article : articles) {
2447                            article.setTemplateId(newTemplateId);
2448    
2449                            journalArticlePersistence.update(article, false);
2450                    }
2451            }
2452    
2453            protected void checkStructure(Document contentDoc, Element root)
2454                    throws PortalException {
2455    
2456                    for (Element el : root.elements()) {
2457                            checkStructureField(el, contentDoc);
2458    
2459                            checkStructure(contentDoc, el);
2460                    }
2461            }
2462    
2463            protected void checkStructure(JournalArticle article)
2464                    throws DocumentException, PortalException, SystemException {
2465    
2466                    Group companyGroup = groupLocalService.getCompanyGroup(
2467                            article.getCompanyId());
2468    
2469                    JournalStructure structure = null;
2470    
2471                    try {
2472                            structure = journalStructurePersistence.findByG_S(
2473                                    article.getGroupId(), article.getStructureId());
2474                    }
2475                    catch (NoSuchStructureException nsse) {
2476                            structure = journalStructurePersistence.findByG_S(
2477                                    companyGroup.getGroupId(), article.getStructureId());
2478                    }
2479    
2480                    String content = GetterUtil.getString(article.getContent());
2481    
2482                    Document contentDoc = SAXReaderUtil.read(content);
2483                    Document xsdDoc = SAXReaderUtil.read(structure.getXsd());
2484    
2485                    try {
2486                            checkStructure(contentDoc, xsdDoc.getRootElement());
2487                    }
2488                    catch (StructureXsdException sxsde) {
2489                            long groupId = article.getGroupId();
2490                            String articleId = article.getArticleId();
2491                            double version = article.getVersion();
2492    
2493                            if (_log.isWarnEnabled()) {
2494                                    _log.warn(
2495                                            "Article {groupId=" + groupId + ", articleId=" +
2496                                                    articleId + ", version=" + version +
2497                                                            "} has content that does not match its " +
2498                                                                    "structure: " + sxsde.getMessage());
2499                            }
2500                    }
2501            }
2502    
2503            protected void checkStructureField(Element el, Document contentDoc)
2504                    throws PortalException {
2505    
2506                    StringBuilder elPath = new StringBuilder();
2507    
2508                    elPath.append(el.attributeValue("name"));
2509    
2510                    Element elParent = el.getParent();
2511    
2512                    for (;;) {
2513                            if ((elParent == null) ||
2514                                    (elParent.getName().equals("root"))) {
2515    
2516                                    break;
2517                            }
2518    
2519                            elPath.insert(
2520                                    0, elParent.attributeValue("name") + StringPool.COMMA);
2521    
2522                            elParent = elParent.getParent();
2523                    }
2524    
2525                    String[] elPathNames = StringUtil.split(elPath.toString());
2526    
2527                    Element contentEl = contentDoc.getRootElement();
2528    
2529                    for (String _elPathName : elPathNames) {
2530                            boolean foundEl = false;
2531    
2532                            for (Element tempEl : contentEl.elements()) {
2533                                    if (_elPathName.equals(
2534                                                    tempEl.attributeValue("name", StringPool.BLANK))) {
2535    
2536                                            contentEl = tempEl;
2537                                            foundEl = true;
2538    
2539                                            break;
2540                                    }
2541                            }
2542    
2543                            if (!foundEl) {
2544                                    String elType = contentEl.attributeValue(
2545                                            "type", StringPool.BLANK);
2546    
2547                                    if (!elType.equals("list") && !elType.equals("multi-list")) {
2548                                            throw new StructureXsdException(elPath.toString());
2549                                    }
2550    
2551                                    break;
2552                            }
2553                    }
2554            }
2555    
2556            protected void copyArticleImages(
2557                            JournalArticle oldArticle, JournalArticle newArticle)
2558                    throws Exception {
2559    
2560                    Document contentDoc = SAXReaderUtil.read(oldArticle.getContent());
2561    
2562                    XPath xpathSelector = SAXReaderUtil.createXPath(
2563                            "//dynamic-element[@type='image']");
2564    
2565                    List<Node> imageNodes = xpathSelector.selectNodes(contentDoc);
2566    
2567                    for (Node imageNode : imageNodes) {
2568                            Element imageEl = (Element)imageNode;
2569    
2570                            String instanceId = imageEl.attributeValue("instance-id");
2571                            String name = imageEl.attributeValue("name");
2572    
2573                            List<Element> dynamicContentEls = imageEl.elements(
2574                                    "dynamic-content");
2575    
2576                            for (Element dynamicContentEl : dynamicContentEls) {
2577                                    long imageId = GetterUtil.getLong(
2578                                            dynamicContentEl.attributeValue("id"));
2579                                    String languageId = dynamicContentEl.attributeValue(
2580                                            "language-id");
2581    
2582                                    Image oldImage = null;
2583    
2584                                    try {
2585                                            oldImage = imageLocalService.getImage(imageId);
2586                                    }
2587                                    catch (NoSuchImageException nsie) {
2588                                            continue;
2589                                    }
2590    
2591                                    imageId = journalArticleImageLocalService.getArticleImageId(
2592                                            newArticle.getGroupId(), newArticle.getArticleId(),
2593                                            newArticle.getVersion(), instanceId, name, languageId);
2594    
2595                                    imageLocalService.updateImage(imageId, oldImage.getTextObj());
2596    
2597                                    String elContent =
2598                                            "/image/journal/article?img_id=" + imageId + "&t=" +
2599                                                    WebServerServletTokenUtil.getToken(imageId);
2600    
2601                                    dynamicContentEl.setText(elContent);
2602                                    dynamicContentEl.addAttribute("id", String.valueOf(imageId));
2603                            }
2604                    }
2605    
2606                    newArticle.setContent(contentDoc.formattedString());
2607            }
2608    
2609            protected void format(
2610                            User user, long groupId, String articleId, double version,
2611                            boolean incrementVersion, Element root, Map<String, byte[]> images)
2612                    throws PortalException, SystemException {
2613    
2614                    for (Element element : root.elements()) {
2615                            String elInstanceId = element.attributeValue(
2616                                    "instance-id", StringPool.BLANK);
2617                            String elName = element.attributeValue("name", StringPool.BLANK);
2618                            String elType = element.attributeValue("type", StringPool.BLANK);
2619    
2620                            if (elType.equals("image")) {
2621                                    formatImage(
2622                                            groupId, articleId, version, incrementVersion, element,
2623                                            elInstanceId, elName, images);
2624                            }
2625                            else if (elType.equals("text_area") || elType.equals("text") ||
2626                                             elType.equals("text_box")) {
2627    
2628                                    List<Element> dynamicContentElements = element.elements(
2629                                            "dynamic-content");
2630    
2631                                    for (Element dynamicContentElement : dynamicContentElements) {
2632                                            String dynamicContent = dynamicContentElement.getText();
2633    
2634                                            if (Validator.isNotNull(dynamicContent)) {
2635                                                    dynamicContent = SanitizerUtil.sanitize(
2636                                                            user.getCompanyId(), groupId, user.getUserId(),
2637                                                            JournalArticle.class.getName(), 0,
2638                                                            ContentTypes.TEXT_HTML, dynamicContent);
2639    
2640                                                    dynamicContentElement.setText(dynamicContent);
2641                                            }
2642                                    }
2643                            }
2644    
2645                            format(
2646                                    user, groupId, articleId, version, incrementVersion, element,
2647                                    images);
2648                    }
2649            }
2650    
2651            protected String format(
2652                            User user, long groupId, String articleId, double version,
2653                            boolean incrementVersion, String content, String structureId,
2654                            Map<String, byte[]> images)
2655                    throws PortalException, SystemException {
2656    
2657                    Document document = null;
2658    
2659                    try {
2660                            document = SAXReaderUtil.read(content);
2661    
2662                            Element rootElement = document.getRootElement();
2663    
2664                            if (Validator.isNotNull(structureId)) {
2665                                    format(
2666                                            user, groupId, articleId, version, incrementVersion,
2667                                            rootElement, images);
2668                            }
2669                            else {
2670                                    List<Element> staticContentElements = rootElement.elements(
2671                                            "static-content");
2672    
2673                                    for (Element staticContentElement : staticContentElements) {
2674                                            String staticContent = staticContentElement.getText();
2675    
2676                                            staticContent = SanitizerUtil.sanitize(
2677                                                    user.getCompanyId(), groupId, user.getUserId(),
2678                                                    JournalArticle.class.getName(), 0,
2679                                                    ContentTypes.TEXT_HTML, staticContent);
2680    
2681                                            staticContentElement.setText(staticContent);
2682                                    }
2683                            }
2684    
2685                            content = DDMXMLUtil.formatXML(document);
2686                    }
2687                    catch (DocumentException de) {
2688                            _log.error(de);
2689                    }
2690                    catch (IOException ioe) {
2691                            _log.error(ioe);
2692                    }
2693    
2694                    content = HtmlUtil.replaceMsWordCharacters(content);
2695    
2696                    return content;
2697            }
2698    
2699            protected void formatImage(
2700                            long groupId, String articleId, double version,
2701                            boolean incrementVersion, Element el, String elInstanceId,
2702                            String elName, Map<String, byte[]> images)
2703                    throws PortalException, SystemException {
2704    
2705                    List<Element> imageContents = el.elements("dynamic-content");
2706    
2707                    for (Element dynamicContent : imageContents) {
2708                            String elLanguage = dynamicContent.attributeValue(
2709                                    "language-id", StringPool.BLANK);
2710    
2711                            if (!elLanguage.equals(StringPool.BLANK)) {
2712                                    elLanguage = "_" + elLanguage;
2713                            }
2714    
2715                            long imageId =
2716                                    journalArticleImageLocalService.getArticleImageId(
2717                                            groupId, articleId, version, elInstanceId, elName,
2718                                            elLanguage);
2719    
2720                            double oldVersion = MathUtil.format(version - 0.1, 1, 1);
2721    
2722                            long oldImageId = 0;
2723    
2724                            if ((oldVersion >= 1) && incrementVersion) {
2725                                    oldImageId =
2726                                            journalArticleImageLocalService.getArticleImageId(
2727                                                    groupId, articleId, oldVersion, elInstanceId, elName,
2728                                                    elLanguage);
2729                            }
2730    
2731                            String elContent =
2732                                    "/image/journal/article?img_id=" + imageId + "&t=" +
2733                                            WebServerServletTokenUtil.getToken(imageId);
2734    
2735                            if (dynamicContent.getText().equals("delete")) {
2736                                    dynamicContent.setText(StringPool.BLANK);
2737    
2738                                    imageLocalService.deleteImage(imageId);
2739    
2740                                    String defaultElLanguage = "";
2741    
2742                                    if (!Validator.isNotNull(elLanguage)) {
2743                                            defaultElLanguage =
2744                                                    "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2745                                    }
2746    
2747                                    long defaultImageId =
2748                                            journalArticleImageLocalService.getArticleImageId(
2749                                                    groupId, articleId, version, elInstanceId, elName,
2750                                                    defaultElLanguage);
2751    
2752                                    imageLocalService.deleteImage(defaultImageId);
2753    
2754                                    continue;
2755                            }
2756    
2757                            byte[] bytes = images.get(elInstanceId + "_" + elName + elLanguage);
2758    
2759                            if (bytes != null && (bytes.length > 0)) {
2760                                    dynamicContent.setText(elContent);
2761                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2762    
2763                                    imageLocalService.updateImage(imageId, bytes);
2764    
2765                                    continue;
2766                            }
2767    
2768                            if ((version > JournalArticleConstants.VERSION_DEFAULT) &&
2769                                    (incrementVersion)) {
2770    
2771                                    Image oldImage = null;
2772    
2773                                    if (oldImageId > 0) {
2774                                            oldImage = imageLocalService.getImage(oldImageId);
2775                                    }
2776    
2777                                    if (oldImage != null) {
2778                                            dynamicContent.setText(elContent);
2779                                            dynamicContent.addAttribute("id", String.valueOf(imageId));
2780    
2781                                            bytes = oldImage.getTextObj();
2782    
2783                                            imageLocalService.updateImage(imageId, bytes);
2784                                    }
2785    
2786                                    continue;
2787                            }
2788    
2789                            Image image = imageLocalService.getImage(imageId);
2790    
2791                            if (image != null) {
2792                                    dynamicContent.setText(elContent);
2793                                    dynamicContent.addAttribute("id", String.valueOf(imageId));
2794    
2795                                    continue;
2796                            }
2797    
2798                            long contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2799                                    dynamicContent.getText(), "img_id"));
2800    
2801                            if (contentImageId <= 0) {
2802                                    contentImageId = GetterUtil.getLong(HttpUtil.getParameter(
2803                                            dynamicContent.getText(), "img_id", false));
2804                            }
2805    
2806                            if (contentImageId > 0) {
2807                                    image = imageLocalService.getImage(contentImageId);
2808    
2809                                    if (image != null) {
2810                                            dynamicContent.addAttribute(
2811                                                    "id", String.valueOf(contentImageId));
2812    
2813                                            continue;
2814                                    }
2815                            }
2816    
2817                            String defaultElLanguage = "";
2818    
2819                            if (!Validator.isNotNull(elLanguage)) {
2820                                    defaultElLanguage =
2821                                            "_" + LocaleUtil.toLanguageId(LocaleUtil.getDefault());
2822                            }
2823    
2824                            long defaultImageId =
2825                                    journalArticleImageLocalService.getArticleImageId(
2826                                            groupId, articleId, version, elInstanceId, elName,
2827                                            defaultElLanguage);
2828    
2829                            Image defaultImage = imageLocalService.getImage(defaultImageId);
2830    
2831                            if (defaultImage != null) {
2832                                    dynamicContent.setText(elContent);
2833                                    dynamicContent.addAttribute(
2834                                            "id", String.valueOf(defaultImageId));
2835    
2836                                    bytes = defaultImage.getTextObj();
2837    
2838                                    imageLocalService.updateImage(defaultImageId, bytes);
2839    
2840                                    continue;
2841                            }
2842    
2843                            dynamicContent.setText(StringPool.BLANK);
2844                    }
2845            }
2846    
2847            protected long getClassTypeId(JournalArticle article) {
2848                    long classTypeId = 0;
2849    
2850                    try {
2851                            JournalStructure structure = journalStructurePersistence.fetchByG_S(
2852                                    article.getGroupId(), article.getStructureId());
2853    
2854                            if (structure == null) {
2855                                    Group companyGroup = groupLocalService.getCompanyGroup(
2856                                            article.getCompanyId());
2857    
2858                                    structure = journalStructurePersistence.fetchByG_S(
2859                                            companyGroup.getGroupId(), article.getStructureId());
2860                            }
2861    
2862                            if (structure != null) {
2863                                    classTypeId = structure.getId();
2864                            }
2865                    }
2866                    catch (Exception e) {
2867                            _log.error(e, e);
2868                    }
2869    
2870                    return classTypeId;
2871            }
2872    
2873            protected Date[] getDateInterval(
2874                            long groupId, String articleId, Date earliestDisplayDate,
2875                            Date latestExpirationDate)
2876                    throws SystemException {
2877    
2878                    Date[] dateInterval = new Date[2];
2879    
2880                    List<JournalArticle> articles = journalArticlePersistence.findByG_A_ST(
2881                            groupId, articleId, WorkflowConstants.STATUS_APPROVED);
2882    
2883                    boolean expiringArticle = true;
2884    
2885                    if (latestExpirationDate == null) {
2886                            expiringArticle = false;
2887                    }
2888    
2889                    for (JournalArticle article : articles) {
2890                            if ((earliestDisplayDate == null) ||
2891                                    ((article.getDisplayDate() != null) &&
2892                                     earliestDisplayDate.after(article.getDisplayDate()))) {
2893    
2894                                    earliestDisplayDate = article.getDisplayDate();
2895                            }
2896    
2897                            if (expiringArticle &&
2898                                    ((latestExpirationDate == null) ||
2899                                     ((article.getExpirationDate() != null) &&
2900                                      latestExpirationDate.before(article.getExpirationDate())))) {
2901    
2902                                    latestExpirationDate = article.getExpirationDate();
2903                            }
2904    
2905                            if (expiringArticle && (article.getExpirationDate() == null) &&
2906                                    (latestExpirationDate != null)) {
2907    
2908                                    expiringArticle = false;
2909                            }
2910                    }
2911    
2912                    dateInterval[0] = earliestDisplayDate;
2913                    dateInterval[1] = latestExpirationDate;
2914    
2915                    return dateInterval;
2916            }
2917    
2918            protected String getUniqueUrlTitle(
2919                            long id, long groupId, String articleId, String title)
2920                    throws PortalException, SystemException {
2921    
2922                    String urlTitle = JournalUtil.getUrlTitle(id, title);
2923    
2924                    String newUrlTitle = ModelHintsUtil.trimString(
2925                            JournalArticle.class.getName(), "urlTitle", urlTitle);
2926    
2927                    for (int i = 1;; i++) {
2928                            JournalArticle article = null;
2929    
2930                            try {
2931                                    article = getArticleByUrlTitle(groupId, newUrlTitle);
2932                            }
2933                            catch (NoSuchArticleException nsae) {
2934                            }
2935    
2936                            if ((article == null) || article.getArticleId().equals(articleId)) {
2937                                    break;
2938                            }
2939                            else {
2940                                    String suffix = StringPool.DASH + i;
2941    
2942                                    String prefix = newUrlTitle;
2943    
2944                                    if (newUrlTitle.length() > suffix.length()) {
2945                                            prefix = newUrlTitle.substring(
2946                                                    0, newUrlTitle.length() - suffix.length());
2947                                    }
2948    
2949                                    newUrlTitle = prefix + suffix;
2950                            }
2951                    }
2952    
2953                    return newUrlTitle;
2954            }
2955    
2956            protected void notifySubscribers(
2957                            JournalArticle article, ServiceContext serviceContext)
2958                    throws PortalException, SystemException {
2959    
2960                    if (!article.isApproved()) {
2961                            return;
2962                    }
2963    
2964                    String articleURL = PortalUtil.getControlPanelFullURL(
2965                            serviceContext.getScopeGroupId(), PortletKeys.JOURNAL, null);
2966    
2967                    if (Validator.isNull(articleURL)) {
2968                            return;
2969                    }
2970    
2971                    PortletPreferences preferences =
2972                            ServiceContextUtil.getPortletPreferences(serviceContext);
2973    
2974                    if (preferences == null) {
2975                            long ownerId = article.getGroupId();
2976                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
2977                            long plid = PortletKeys.PREFS_PLID_SHARED;
2978                            String portletId = PortletKeys.JOURNAL;
2979                            String defaultPreferences = null;
2980    
2981                            preferences = portletPreferencesLocalService.getPreferences(
2982                                    article.getCompanyId(), ownerId, ownerType, plid, portletId,
2983                                    defaultPreferences);
2984                    }
2985    
2986                    if ((article.getVersion() == 1.0) &&
2987                            JournalUtil.getEmailArticleAddedEnabled(preferences)) {
2988                    }
2989                    else if ((article.getVersion() != 1.0) &&
2990                                     JournalUtil.getEmailArticleUpdatedEnabled(preferences)) {
2991                    }
2992                    else {
2993                            return;
2994                    }
2995    
2996                    String fromName = JournalUtil.getEmailFromName(
2997                            preferences, article.getCompanyId());
2998                    String fromAddress = JournalUtil.getEmailFromAddress(
2999                            preferences, article.getCompanyId());
3000    
3001                    String subject = null;
3002                    String body = null;
3003    
3004                    if (article.getVersion() == 1.0) {
3005                            subject = JournalUtil.getEmailArticleAddedSubject(preferences);
3006                            body = JournalUtil.getEmailArticleAddedBody(preferences);
3007                    }
3008                    else {
3009                            subject = JournalUtil.getEmailArticleUpdatedSubject(preferences);
3010                            body = JournalUtil.getEmailArticleUpdatedBody(preferences);
3011                    }
3012    
3013                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3014    
3015                    subscriptionSender.setBody(body);
3016                    subscriptionSender.setCompanyId(article.getCompanyId());
3017                    subscriptionSender.setContextAttributes(
3018                            "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3019                            article.getTitle(serviceContext.getLanguageId()), "[$ARTICLE_URL$]",
3020                            articleURL, "[$ARTICLE_VERSION$]", article.getVersion());
3021                    subscriptionSender.setContextUserPrefix("ARTICLE");
3022                    subscriptionSender.setFrom(fromAddress, fromName);
3023                    subscriptionSender.setHtmlFormat(true);
3024                    subscriptionSender.setMailId("journal_article", article.getId());
3025                    subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3026                    subscriptionSender.setReplyToAddress(fromAddress);
3027                    subscriptionSender.setScopeGroupId(article.getGroupId());
3028                    subscriptionSender.setSubject(subject);
3029                    subscriptionSender.setUserId(article.getUserId());
3030    
3031                    subscriptionSender.addPersistedSubscribers(
3032                            JournalArticle.class.getName(), article.getGroupId());
3033    
3034                    subscriptionSender.flushNotificationsAsync();
3035            }
3036    
3037            protected void saveImages(
3038                            boolean smallImage, long smallImageId, File smallImageFile,
3039                            byte[] smallImageBytes)
3040                    throws PortalException, SystemException {
3041    
3042                    if (smallImage) {
3043                            if ((smallImageFile != null) && (smallImageBytes != null)) {
3044                                    imageLocalService.updateImage(smallImageId, smallImageBytes);
3045                            }
3046                    }
3047                    else {
3048                            imageLocalService.deleteImage(smallImageId);
3049                    }
3050            }
3051    
3052            protected void sendEmail(
3053                            JournalArticle article, String articleURL,
3054                            PortletPreferences preferences, String emailType)
3055                    throws PortalException, SystemException {
3056    
3057                    if (preferences == null) {
3058                            return;
3059                    }
3060                    else if (emailType.equals("denied") &&
3061                            JournalUtil.getEmailArticleApprovalDeniedEnabled(preferences)) {
3062                    }
3063                    else if (emailType.equals("granted") &&
3064                                     JournalUtil.getEmailArticleApprovalGrantedEnabled(
3065                                            preferences)) {
3066                    }
3067                    else if (emailType.equals("requested") &&
3068                                     JournalUtil.getEmailArticleApprovalRequestedEnabled(
3069                                            preferences)) {
3070                    }
3071                    else if (emailType.equals("review") &&
3072                                     JournalUtil.getEmailArticleReviewEnabled(preferences)) {
3073                    }
3074                    else {
3075                            return;
3076                    }
3077    
3078                    Company company = companyPersistence.findByPrimaryKey(
3079                            article.getCompanyId());
3080    
3081                    User user = userPersistence.findByPrimaryKey(article.getUserId());
3082    
3083                    articleURL +=
3084                            "&groupId=" + article.getGroupId() + "&articleId=" +
3085                                    article.getArticleId() + "&version=" + article.getVersion();
3086    
3087                    String fromName = JournalUtil.getEmailFromName(
3088                            preferences, article.getCompanyId());
3089                    String fromAddress = JournalUtil.getEmailFromAddress(
3090                            preferences, article.getCompanyId());
3091    
3092                    String toName = user.getFullName();
3093                    String toAddress = user.getEmailAddress();
3094    
3095                    if (emailType.equals("requested") ||
3096                            emailType.equals("review")) {
3097    
3098                            String tempToName = fromName;
3099                            String tempToAddress = fromAddress;
3100    
3101                            fromName = toName;
3102                            fromAddress = toAddress;
3103    
3104                            toName = tempToName;
3105                            toAddress = tempToAddress;
3106                    }
3107    
3108                    String subject = null;
3109                    String body = null;
3110    
3111                    if (emailType.equals("denied")) {
3112                            subject =
3113                                    JournalUtil.getEmailArticleApprovalDeniedSubject(preferences);
3114                            body = JournalUtil.getEmailArticleApprovalDeniedBody(preferences);
3115                    }
3116                    else if (emailType.equals("granted")) {
3117                            subject =
3118                                    JournalUtil.getEmailArticleApprovalGrantedSubject(preferences);
3119                            body = JournalUtil.getEmailArticleApprovalGrantedBody(preferences);
3120                    }
3121                    else if (emailType.equals("requested")) {
3122                            subject =
3123                                    JournalUtil.getEmailArticleApprovalRequestedSubject(
3124                                    preferences);
3125                            body = JournalUtil.getEmailArticleApprovalRequestedBody(
3126                                    preferences);
3127                    }
3128                    else if (emailType.equals("review")) {
3129                            subject = JournalUtil.getEmailArticleReviewSubject(preferences);
3130                            body = JournalUtil.getEmailArticleReviewBody(preferences);
3131                    }
3132    
3133                    SubscriptionSender subscriptionSender = new SubscriptionSender();
3134    
3135                    subscriptionSender.setBody(body);
3136                    subscriptionSender.setCompanyId(company.getCompanyId());
3137                    subscriptionSender.setContextAttributes(
3138                            "[$ARTICLE_ID$]", article.getArticleId(), "[$ARTICLE_TITLE$]",
3139                            article.getTitle(), "[$ARTICLE_URL$]", articleURL,
3140                            "[$ARTICLE_USER_NAME$]", article.getUserName(),
3141                            "[$ARTICLE_VERSION$]", article.getVersion());
3142                    subscriptionSender.setContextUserPrefix("ARTICLE");
3143                    subscriptionSender.setFrom(fromAddress, fromName);
3144                    subscriptionSender.setHtmlFormat(true);
3145                    subscriptionSender.setMailId("journal_article", article.getId());
3146                    subscriptionSender.setPortletId(PortletKeys.JOURNAL);
3147                    subscriptionSender.setScopeGroupId(article.getGroupId());
3148                    subscriptionSender.setSubject(subject);
3149                    subscriptionSender.setUserId(article.getUserId());
3150    
3151                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
3152    
3153                    subscriptionSender.flushNotificationsAsync();
3154            }
3155    
3156            protected void updatePreviousApprovedArticle(JournalArticle article)
3157                    throws PortalException, SystemException {
3158    
3159                    List<JournalArticle> approvedArticles =
3160                            journalArticlePersistence.findByG_A_ST(
3161                                    article.getGroupId(), article.getArticleId(),
3162                                    WorkflowConstants.STATUS_APPROVED, 0, 2);
3163    
3164                    if (approvedArticles.isEmpty() ||
3165                            ((approvedArticles.size() == 1) &&
3166                             (article.getStatus() == WorkflowConstants.STATUS_APPROVED))) {
3167    
3168                            if (article.isIndexable()) {
3169                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
3170                                            JournalArticle.class);
3171    
3172                                    indexer.delete(article);
3173                            }
3174    
3175                            assetEntryLocalService.updateVisible(
3176                                    JournalArticle.class.getName(), article.getResourcePrimKey(),
3177                                    false);
3178                    }
3179                    else {
3180                            JournalArticle previousApprovedArticle = approvedArticles.get(0);
3181    
3182                            if (article.getStatus() == WorkflowConstants.STATUS_APPROVED) {
3183                                    previousApprovedArticle = approvedArticles.get(1);
3184                            }
3185    
3186                            if (article.isIndexable()) {
3187                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
3188                                            JournalArticle.class);
3189    
3190                                    indexer.reindex(previousApprovedArticle);
3191                            }
3192                    }
3193            }
3194    
3195            protected void updateUrlTitles(
3196                            long groupId, String articleId, String urlTitle)
3197                    throws SystemException {
3198    
3199                    List<JournalArticle> articles = journalArticlePersistence.findByG_A(
3200                            groupId, articleId);
3201    
3202                    for (JournalArticle article : articles) {
3203                            if (!article.getUrlTitle().equals(urlTitle)) {
3204                                    article.setUrlTitle(urlTitle);
3205    
3206                                    journalArticlePersistence.update(article, false);
3207                            }
3208                    }
3209            }
3210    
3211            protected void validate(
3212                            long companyId, long groupId, long classNameId,
3213                            Map<Locale, String> titleMap, String content, String type,
3214                            String structureId, String templateId, boolean smallImage,
3215                            String smallImageURL, File smallImageFile, byte[] smallImageBytes)
3216                    throws PortalException, SystemException {
3217    
3218                    Locale defaultLocale = LocaleUtil.fromLanguageId(
3219                            LocalizationUtil.getDefaultLocale(content));
3220    
3221                    if ((classNameId == 0) &&
3222                            (titleMap.isEmpty() ||
3223                             Validator.isNull(titleMap.get(defaultLocale)))) {
3224    
3225                            throw new ArticleTitleException();
3226                    }
3227                    else if (Validator.isNull(type)) {
3228                            throw new ArticleTypeException();
3229                    }
3230    
3231                    validateContent(content);
3232    
3233                    if (Validator.isNotNull(structureId)) {
3234                            Group companyGroup = groupLocalService.getCompanyGroup(companyId);
3235    
3236                            try {
3237                                    journalStructurePersistence.findByG_S(
3238                                            groupId, structureId);
3239                            }
3240                            catch (NoSuchStructureException nsse) {
3241                                    journalStructurePersistence.findByG_S(
3242                                            companyGroup.getGroupId(), structureId);
3243                            }
3244    
3245                            JournalTemplate template = null;
3246    
3247                            if (Validator.isNotNull(templateId)) {
3248                                    try {
3249                                            template = journalTemplatePersistence.findByG_T(
3250                                                    groupId, templateId);
3251                                    }
3252                                    catch (NoSuchTemplateException nste) {
3253                                            template = journalTemplatePersistence.findByG_T(
3254                                                    companyGroup.getGroupId(), templateId);
3255                                    }
3256    
3257                                    if (!template.getStructureId().equals(structureId)) {
3258                                            throw new NoSuchTemplateException();
3259                                    }
3260                            }
3261                            else if (classNameId == 0) {
3262                                    throw new NoSuchTemplateException();
3263                            }
3264                    }
3265    
3266                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
3267                            PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
3268    
3269                    if (smallImage && Validator.isNull(smallImageURL) &&
3270                            (smallImageFile != null) && (smallImageBytes != null)) {
3271    
3272                            String smallImageName = smallImageFile.getName();
3273    
3274                            if (smallImageName != null) {
3275                                    boolean validSmallImageExtension = false;
3276    
3277                                    for (String _imageExtension : imageExtensions) {
3278                                            if (StringPool.STAR.equals(_imageExtension) ||
3279                                                    StringUtil.endsWith(smallImageName, _imageExtension)) {
3280    
3281                                                    validSmallImageExtension = true;
3282    
3283                                                    break;
3284                                            }
3285                                    }
3286    
3287                                    if (!validSmallImageExtension) {
3288                                            throw new ArticleSmallImageNameException(smallImageName);
3289                                    }
3290                            }
3291    
3292                            long smallImageMaxSize = PrefsPropsUtil.getLong(
3293                                    PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
3294    
3295                            if ((smallImageMaxSize > 0) &&
3296                                    ((smallImageBytes == null) ||
3297                                     (smallImageBytes.length > smallImageMaxSize))) {
3298    
3299                                    throw new ArticleSmallImageSizeException();
3300                            }
3301                    }
3302            }
3303    
3304            protected void validate(
3305                            long companyId, long groupId, long classNameId, String articleId,
3306                            boolean autoArticleId, double version, Map<Locale, String> titleMap,
3307                            String content, String type, String structureId, String templateId,
3308                            boolean smallImage, String smallImageURL, File smallImageFile,
3309                            byte[] smallImageBytes)
3310                    throws PortalException, SystemException {
3311    
3312                    if (!autoArticleId) {
3313                            validate(groupId, articleId);
3314                    }
3315    
3316                    validate(
3317                            companyId, groupId, classNameId, titleMap, content, type,
3318                            structureId,templateId, smallImage, smallImageURL, smallImageFile,
3319                            smallImageBytes);
3320            }
3321    
3322            protected void validate(long groupId, String articleId)
3323                    throws PortalException, SystemException {
3324    
3325                    if ((Validator.isNull(articleId)) ||
3326                            (articleId.indexOf(CharPool.SPACE) != -1)) {
3327    
3328                            throw new ArticleIdException();
3329                    }
3330    
3331                    if (journalArticlePersistence.countByG_A(groupId, articleId) > 0) {
3332                            throw new DuplicateArticleIdException();
3333                    }
3334            }
3335    
3336            protected void validateContent(String content) throws PortalException {
3337                    if (Validator.isNull(content)) {
3338                            throw new ArticleContentException();
3339                    }
3340    
3341                    try {
3342                            SAXReaderUtil.read(content);
3343                    }
3344                    catch (DocumentException de) {
3345                            throw new ArticleContentException();
3346                    }
3347            }
3348    
3349            private static long _JOURNAL_ARTICLE_CHECK_INTERVAL =
3350                    PropsValues.JOURNAL_ARTICLE_CHECK_INTERVAL * Time.MINUTE;
3351    
3352            private static Log _log = LogFactoryUtil.getLog(
3353                    JournalArticleLocalServiceImpl.class);
3354    
3355    }