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