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