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