001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.action;
016    
017    import com.liferay.portal.LocaleException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.portlet.LiferayPortletURL;
022    import com.liferay.portal.kernel.portlet.LiferayWindowState;
023    import com.liferay.portal.kernel.servlet.SessionErrors;
024    import com.liferay.portal.kernel.servlet.SessionMessages;
025    import com.liferay.portal.kernel.upload.LiferayFileItemException;
026    import com.liferay.portal.kernel.upload.UploadException;
027    import com.liferay.portal.kernel.upload.UploadPortletRequest;
028    import com.liferay.portal.kernel.util.ArrayUtil;
029    import com.liferay.portal.kernel.util.Constants;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.HtmlUtil;
032    import com.liferay.portal.kernel.util.HttpUtil;
033    import com.liferay.portal.kernel.util.LocaleUtil;
034    import com.liferay.portal.kernel.util.LocalizationUtil;
035    import com.liferay.portal.kernel.util.MapUtil;
036    import com.liferay.portal.kernel.util.ParamUtil;
037    import com.liferay.portal.kernel.util.StringPool;
038    import com.liferay.portal.kernel.util.StringUtil;
039    import com.liferay.portal.kernel.util.Validator;
040    import com.liferay.portal.kernel.workflow.WorkflowConstants;
041    import com.liferay.portal.model.Layout;
042    import com.liferay.portal.security.auth.PrincipalException;
043    import com.liferay.portal.service.LayoutLocalServiceUtil;
044    import com.liferay.portal.service.ServiceContext;
045    import com.liferay.portal.service.ServiceContextFactory;
046    import com.liferay.portal.struts.PortletAction;
047    import com.liferay.portal.theme.ThemeDisplay;
048    import com.liferay.portal.util.PortalUtil;
049    import com.liferay.portal.util.WebKeys;
050    import com.liferay.portlet.PortletURLFactoryUtil;
051    import com.liferay.portlet.asset.AssetCategoryException;
052    import com.liferay.portlet.asset.AssetTagException;
053    import com.liferay.portlet.assetpublisher.util.AssetPublisherUtil;
054    import com.liferay.portlet.documentlibrary.FileSizeException;
055    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
056    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
057    import com.liferay.portlet.dynamicdatamapping.StorageFieldRequiredException;
058    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
059    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
060    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
061    import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;
062    import com.liferay.portlet.journal.ArticleContentException;
063    import com.liferay.portlet.journal.ArticleContentSizeException;
064    import com.liferay.portlet.journal.ArticleDisplayDateException;
065    import com.liferay.portlet.journal.ArticleExpirationDateException;
066    import com.liferay.portlet.journal.ArticleIdException;
067    import com.liferay.portlet.journal.ArticleSmallImageNameException;
068    import com.liferay.portlet.journal.ArticleSmallImageSizeException;
069    import com.liferay.portlet.journal.ArticleTitleException;
070    import com.liferay.portlet.journal.ArticleTypeException;
071    import com.liferay.portlet.journal.ArticleVersionException;
072    import com.liferay.portlet.journal.DuplicateArticleIdException;
073    import com.liferay.portlet.journal.NoSuchArticleException;
074    import com.liferay.portlet.journal.NoSuchArticleImageException;
075    import com.liferay.portlet.journal.asset.JournalArticleAssetRenderer;
076    import com.liferay.portlet.journal.model.JournalArticle;
077    import com.liferay.portlet.journal.service.JournalArticleServiceUtil;
078    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
079    import com.liferay.portlet.journal.util.JournalConverterUtil;
080    import com.liferay.portlet.journal.util.JournalUtil;
081    
082    import java.io.File;
083    
084    import java.util.Calendar;
085    import java.util.HashMap;
086    import java.util.Locale;
087    import java.util.Map;
088    
089    import javax.portlet.ActionRequest;
090    import javax.portlet.ActionResponse;
091    import javax.portlet.PortletConfig;
092    import javax.portlet.PortletPreferences;
093    import javax.portlet.PortletRequest;
094    import javax.portlet.PortletURL;
095    import javax.portlet.RenderRequest;
096    import javax.portlet.RenderResponse;
097    import javax.portlet.WindowState;
098    
099    import org.apache.struts.action.ActionForm;
100    import org.apache.struts.action.ActionForward;
101    import org.apache.struts.action.ActionMapping;
102    
103    /**
104     * @author Brian Wing Shun Chan
105     * @author Raymond Aug??
106     * @author Eduardo Lundgren
107     * @author Juan Fern??ndez
108     * @author Levente Hud??k
109     */
110    public class EditArticleAction extends PortletAction {
111    
112            public static final String VERSION_SEPARATOR = "_version_";
113    
114            @Override
115            public void processAction(
116                            ActionMapping actionMapping, ActionForm actionForm,
117                            PortletConfig portletConfig, ActionRequest actionRequest,
118                            ActionResponse actionResponse)
119                    throws Exception {
120    
121                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
122    
123                    JournalArticle article = null;
124                    String oldUrlTitle = StringPool.BLANK;
125    
126                    try {
127                            UploadException uploadException =
128                                    (UploadException)actionRequest.getAttribute(
129                                            WebKeys.UPLOAD_EXCEPTION);
130    
131                            if (uploadException != null) {
132                                    if (uploadException.isExceededLiferayFileItemSizeLimit()) {
133                                            throw new LiferayFileItemException();
134                                    }
135                                    else if (uploadException.isExceededSizeLimit()) {
136                                            throw new ArticleContentSizeException();
137                                    }
138    
139                                    throw new PortalException(uploadException.getCause());
140                            }
141                            else if (Validator.isNull(cmd)) {
142                                    return;
143                            }
144                            else if (cmd.equals(Constants.ADD) ||
145                                             cmd.equals(Constants.PREVIEW) ||
146                                             cmd.equals(Constants.TRANSLATE) ||
147                                             cmd.equals(Constants.UPDATE)) {
148    
149                                    Object[] contentAndImages = updateArticle(actionRequest);
150    
151                                    article = (JournalArticle)contentAndImages[0];
152                                    oldUrlTitle = ((String)contentAndImages[1]);
153                            }
154                            else if (cmd.equals(Constants.DELETE)) {
155                                    deleteArticles(actionRequest, false);
156                            }
157                            else if (cmd.equals(Constants.DELETE_TRANSLATION)) {
158                                    removeArticlesLocale(actionRequest);
159                            }
160                            else if (cmd.equals(Constants.EXPIRE)) {
161                                    expireArticles(actionRequest);
162                            }
163                            else if (cmd.equals(Constants.MOVE)) {
164                                    moveArticles(actionRequest);
165                            }
166                            else if (cmd.equals(Constants.MOVE_TO_TRASH)) {
167                                    deleteArticles(actionRequest, true);
168                            }
169                            else if (cmd.equals(Constants.RESTORE)) {
170                                    restoreArticles(actionRequest);
171                            }
172                            else if (cmd.equals(Constants.SUBSCRIBE)) {
173                                    subscribeArticles(actionRequest);
174                            }
175                            else if (cmd.equals(Constants.UNSUBSCRIBE)) {
176                                    unsubscribeArticles(actionRequest);
177                            }
178    
179                            String redirect = ParamUtil.getString(actionRequest, "redirect");
180    
181                            int workflowAction = ParamUtil.getInteger(
182                                    actionRequest, "workflowAction",
183                                    WorkflowConstants.ACTION_PUBLISH);
184    
185                            String portletId = HttpUtil.getParameter(redirect, "p_p_id", false);
186    
187                            String namespace = PortalUtil.getPortletNamespace(portletId);
188    
189                            if (Validator.isNotNull(oldUrlTitle)) {
190                                    String oldRedirectParam = namespace + "redirect";
191    
192                                    String oldRedirect = HttpUtil.getParameter(
193                                            redirect, oldRedirectParam, false);
194    
195                                    if (Validator.isNotNull(oldRedirect)) {
196                                            String newRedirect = HttpUtil.decodeURL(oldRedirect);
197    
198                                            newRedirect = StringUtil.replace(
199                                                    newRedirect, oldUrlTitle, article.getUrlTitle());
200                                            newRedirect = StringUtil.replace(
201                                                    newRedirect, oldRedirectParam, "redirect");
202    
203                                            redirect = StringUtil.replace(
204                                                    redirect, oldRedirect, newRedirect);
205                                    }
206                            }
207    
208                            if (cmd.equals(Constants.DELETE) &&
209                                    !ActionUtil.hasArticle(actionRequest)) {
210    
211                                    String referringPortletResource = ParamUtil.getString(
212                                            actionRequest, "referringPortletResource");
213    
214                                    if (Validator.isNotNull(referringPortletResource)) {
215                                            setForward(
216                                                    actionRequest,
217                                                    "portlet.journal.asset.add_asset_redirect");
218    
219                                            return;
220                                    }
221                                    else {
222                                            ThemeDisplay themeDisplay =
223                                                    (ThemeDisplay)actionRequest.getAttribute(
224                                                            WebKeys.THEME_DISPLAY);
225    
226                                            PortletURL portletURL = PortletURLFactoryUtil.create(
227                                                    actionRequest, portletConfig.getPortletName(),
228                                                    themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
229    
230                                            redirect = portletURL.toString();
231                                    }
232                            }
233    
234                            if (cmd.equals(Constants.DELETE_TRANSLATION) ||
235                                    cmd.equals(Constants.TRANSLATE)) {
236    
237                                    setForward(
238                                            actionRequest,
239                                            "portlet.journal.update_translation_redirect");
240                            }
241                            else if ((article != null) &&
242                                             (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT)) {
243    
244                                    redirect = getSaveAndContinueRedirect(
245                                            portletConfig, actionRequest, article, redirect);
246    
247                                    if (cmd.equals(Constants.PREVIEW)) {
248                                            SessionMessages.add(actionRequest, "previewRequested");
249    
250                                            hideDefaultSuccessMessage(actionRequest);
251                                    }
252    
253                                    sendRedirect(actionRequest, actionResponse, redirect);
254                            }
255                            else {
256                                    WindowState windowState = actionRequest.getWindowState();
257    
258                                    if (!windowState.equals(LiferayWindowState.POP_UP)) {
259                                            sendRedirect(actionRequest, actionResponse, redirect);
260                                    }
261                                    else {
262                                            redirect = PortalUtil.escapeRedirect(redirect);
263    
264                                            if (Validator.isNotNull(redirect)) {
265                                                    if (cmd.equals(Constants.ADD) && (article != null)) {
266                                                            redirect = HttpUtil.addParameter(
267                                                                    redirect, namespace + "className",
268                                                                    JournalArticle.class.getName());
269                                                            redirect = HttpUtil.addParameter(
270                                                                    redirect, namespace + "classPK",
271                                                                    JournalArticleAssetRenderer.getClassPK(
272                                                                            article));
273                                                    }
274    
275                                                    actionResponse.sendRedirect(redirect);
276                                            }
277                                    }
278                            }
279                    }
280                    catch (Exception e) {
281                            if (e instanceof NoSuchArticleException ||
282                                    e instanceof NoSuchStructureException ||
283                                    e instanceof NoSuchTemplateException ||
284                                    e instanceof PrincipalException) {
285    
286                                    SessionErrors.add(actionRequest, e.getClass());
287    
288                                    setForward(actionRequest, "portlet.journal.error");
289                            }
290                            else if (e instanceof ArticleContentException ||
291                                             e instanceof ArticleContentSizeException ||
292                                             e instanceof ArticleDisplayDateException ||
293                                             e instanceof ArticleExpirationDateException ||
294                                             e instanceof ArticleIdException ||
295                                             e instanceof ArticleSmallImageNameException ||
296                                             e instanceof ArticleSmallImageSizeException ||
297                                             e instanceof ArticleTitleException ||
298                                             e instanceof ArticleTypeException ||
299                                             e instanceof ArticleVersionException ||
300                                             e instanceof DuplicateArticleIdException ||
301                                             e instanceof FileSizeException ||
302                                             e instanceof LiferayFileItemException ||
303                                             e instanceof NoSuchArticleImageException ||
304                                             e instanceof StorageFieldRequiredException) {
305    
306                                    SessionErrors.add(actionRequest, e.getClass());
307                            }
308                            else if (e instanceof AssetCategoryException ||
309                                             e instanceof AssetTagException ||
310                                             e instanceof LocaleException) {
311    
312                                    SessionErrors.add(actionRequest, e.getClass(), e);
313                            }
314                            else {
315                                    throw e;
316                            }
317                    }
318            }
319    
320            @Override
321            public ActionForward render(
322                            ActionMapping actionMapping, ActionForm actionForm,
323                            PortletConfig portletConfig, RenderRequest renderRequest,
324                            RenderResponse renderResponse)
325                    throws Exception {
326    
327                    try {
328                            ActionUtil.getArticle(renderRequest);
329                    }
330                    catch (NoSuchArticleException nsae) {
331    
332                            // Let this slide because the user can manually input a article id
333                            // for a new article that does not yet exist.
334    
335                    }
336                    catch (Exception e) {
337                            if (//e instanceof NoSuchArticleException ||
338                                    e instanceof PrincipalException) {
339    
340                                    SessionErrors.add(renderRequest, e.getClass());
341    
342                                    return actionMapping.findForward("portlet.journal.error");
343                            }
344                            else {
345                                    throw e;
346                            }
347                    }
348    
349                    return actionMapping.findForward(
350                            getForward(renderRequest, "portlet.journal.edit_article"));
351            }
352    
353            protected void deleteArticles(
354                            ActionRequest actionRequest, boolean moveToTrash)
355                    throws Exception {
356    
357                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
358                            WebKeys.THEME_DISPLAY);
359    
360                    String deleteEntryTitle = null;
361    
362                    String[] deleteArticleIds = null;
363    
364                    String articleId = ParamUtil.getString(actionRequest, "articleId");
365    
366                    if (Validator.isNotNull(articleId)) {
367                            deleteArticleIds = new String[] {articleId};
368                    }
369                    else {
370                            deleteArticleIds = StringUtil.split(
371                                    ParamUtil.getString(actionRequest, "articleIds"));
372                    }
373    
374                    long[] restoreArticleIds = new long[deleteArticleIds.length];
375    
376                    for (int i = 0; i < deleteArticleIds.length; i++) {
377                            String deleteArticleId = deleteArticleIds[i];
378    
379                            if (moveToTrash) {
380                                    JournalArticle article =
381                                            JournalArticleServiceUtil.moveArticleToTrash(
382                                                    themeDisplay.getScopeGroupId(),
383                                                    HtmlUtil.unescape(deleteArticleId));
384    
385                                    if (i == 0) {
386                                            deleteEntryTitle = article.getTitle(
387                                                    themeDisplay.getLocale());
388                                    }
389    
390                                    restoreArticleIds[i] = article.getResourcePrimKey();
391                            }
392                            else {
393                                    ActionUtil.deleteArticle(
394                                            actionRequest, HtmlUtil.unescape(deleteArticleId));
395                            }
396                    }
397    
398                    if (moveToTrash && (deleteArticleIds.length > 0)) {
399                            Map<String, String[]> data = new HashMap<String, String[]>();
400    
401                            data.put(
402                                    "deleteEntryClassName",
403                                    new String[] {JournalArticle.class.getName()});
404    
405                            if (Validator.isNotNull(deleteEntryTitle)) {
406                                    data.put("deleteEntryTitle", new String[] {deleteEntryTitle});
407                            }
408    
409                            data.put(
410                                    "restoreArticleIds",
411                                    ArrayUtil.toStringArray(restoreArticleIds));
412    
413                            SessionMessages.add(
414                                    actionRequest,
415                                    PortalUtil.getPortletId(actionRequest) +
416                                            SessionMessages.KEY_SUFFIX_DELETE_SUCCESS_DATA, data);
417    
418                            hideDefaultSuccessMessage(actionRequest);
419                    }
420            }
421    
422            protected void expireArticles(ActionRequest actionRequest)
423                    throws Exception {
424    
425                    String articleId = ParamUtil.getString(actionRequest, "articleId");
426    
427                    if (Validator.isNotNull(articleId)) {
428                            ActionUtil.expireArticle(actionRequest, articleId);
429                    }
430                    else {
431                            String[] expireArticleIds = StringUtil.split(
432                                    ParamUtil.getString(actionRequest, "expireArticleIds"));
433    
434                            for (String expireArticleId : expireArticleIds) {
435                                    ActionUtil.expireArticle(
436                                            actionRequest, HtmlUtil.unescape(expireArticleId));
437                            }
438                    }
439            }
440    
441            protected String getSaveAndContinueRedirect(
442                            PortletConfig portletConfig, ActionRequest actionRequest,
443                            JournalArticle article, String redirect)
444                    throws Exception {
445    
446                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
447                            WebKeys.THEME_DISPLAY);
448    
449                    String referringPortletResource = ParamUtil.getString(
450                            actionRequest, "referringPortletResource");
451    
452                    String languageId = ParamUtil.getString(actionRequest, "languageId");
453    
454                    LiferayPortletURL liferayPortletURL = PortletURLFactoryUtil.create(
455                            actionRequest, portletConfig.getPortletName(),
456                            themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
457    
458                    liferayPortletURL.setParameter(
459                            "struts_action", "/journal/edit_article");
460                    liferayPortletURL.setParameter("redirect", redirect, false);
461                    liferayPortletURL.setParameter(
462                            "referringPortletResource", referringPortletResource, false);
463                    liferayPortletURL.setParameter(
464                            "resourcePrimKey", String.valueOf(article.getResourcePrimKey()),
465                            false);
466                    liferayPortletURL.setParameter(
467                            "groupId", String.valueOf(article.getGroupId()), false);
468                    liferayPortletURL.setParameter(
469                            "folderId", String.valueOf(article.getFolderId()), false);
470                    liferayPortletURL.setParameter(
471                            "articleId", article.getArticleId(), false);
472                    liferayPortletURL.setParameter(
473                            "version", String.valueOf(article.getVersion()), false);
474                    liferayPortletURL.setParameter("languageId", languageId, false);
475                    liferayPortletURL.setWindowState(actionRequest.getWindowState());
476    
477                    return liferayPortletURL.toString();
478            }
479    
480            protected void moveArticles(ActionRequest actionRequest) throws Exception {
481                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
482                            WebKeys.THEME_DISPLAY);
483    
484                    String articleId = ParamUtil.getString(actionRequest, "articleId");
485                    long newFolderId = ParamUtil.getLong(actionRequest, "newFolderId");
486    
487                    if (Validator.isNotNull(articleId)) {
488                            JournalArticleServiceUtil.moveArticle(
489                                    themeDisplay.getScopeGroupId(), articleId, newFolderId);
490                    }
491                    else {
492                            String[] articleIds = StringUtil.split(
493                                    ParamUtil.getString(actionRequest, "articleIds"));
494    
495                            for (int i = 0; i < articleIds.length; i++) {
496                                    JournalArticleServiceUtil.moveArticle(
497                                            themeDisplay.getScopeGroupId(), articleIds[i], newFolderId);
498                            }
499                    }
500            }
501    
502            protected void removeArticlesLocale(ActionRequest actionRequest)
503                    throws Exception {
504    
505                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
506    
507                    String[] removeArticleLocaleIds = StringUtil.split(
508                            ParamUtil.getString(actionRequest, "articleIds"));
509    
510                    for (String removeArticleLocaleId : removeArticleLocaleIds) {
511                            int pos = removeArticleLocaleId.lastIndexOf(VERSION_SEPARATOR);
512    
513                            String articleId = removeArticleLocaleId.substring(0, pos);
514                            double version = GetterUtil.getDouble(
515                                    removeArticleLocaleId.substring(
516                                            pos + VERSION_SEPARATOR.length()));
517                            String languageId = ParamUtil.getString(
518                                    actionRequest, "languageId");
519    
520                            JournalArticleServiceUtil.removeArticleLocale(
521                                    groupId, articleId, version, languageId);
522                    }
523            }
524    
525            protected void restoreArticles(ActionRequest actionRequest)
526                    throws Exception {
527    
528                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
529                            WebKeys.THEME_DISPLAY);
530    
531                    String[] restoreEntryIds = StringUtil.split(
532                            ParamUtil.getString(actionRequest, "restoreEntryIds"));
533    
534                    for (String restoreEntryId : restoreEntryIds) {
535                            JournalArticleServiceUtil.restoreArticleFromTrash(
536                                    themeDisplay.getScopeGroupId(), restoreEntryId);
537                    }
538            }
539    
540            protected void subscribeArticles(ActionRequest actionRequest)
541                    throws Exception {
542    
543                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
544                            WebKeys.THEME_DISPLAY);
545    
546                    JournalArticleServiceUtil.subscribe(themeDisplay.getScopeGroupId());
547            }
548    
549            protected void unsubscribeArticles(ActionRequest actionRequest)
550                    throws Exception {
551    
552                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
553                            WebKeys.THEME_DISPLAY);
554    
555                    JournalArticleServiceUtil.unsubscribe(themeDisplay.getScopeGroupId());
556            }
557    
558            protected Object[] updateArticle(ActionRequest actionRequest)
559                    throws Exception {
560    
561                    UploadPortletRequest uploadPortletRequest =
562                            PortalUtil.getUploadPortletRequest(actionRequest);
563    
564                    if (_log.isDebugEnabled()) {
565                            _log.debug(
566                                    "Updating article " +
567                                            MapUtil.toString(uploadPortletRequest.getParameterMap()));
568                    }
569    
570                    String cmd = ParamUtil.getString(uploadPortletRequest, Constants.CMD);
571    
572                    long groupId = ParamUtil.getLong(uploadPortletRequest, "groupId");
573                    long folderId = ParamUtil.getLong(uploadPortletRequest, "folderId");
574                    long classNameId = ParamUtil.getLong(
575                            uploadPortletRequest, "classNameId");
576                    long classPK = ParamUtil.getLong(uploadPortletRequest, "classPK");
577    
578                    String articleId = ParamUtil.getString(
579                            uploadPortletRequest, "articleId");
580    
581                    boolean autoArticleId = ParamUtil.getBoolean(
582                            uploadPortletRequest, "autoArticleId");
583                    double version = ParamUtil.getDouble(uploadPortletRequest, "version");
584                    boolean localized = ParamUtil.getBoolean(
585                            uploadPortletRequest, "localized");
586    
587                    String defaultLanguageId = ParamUtil.getString(
588                            uploadPortletRequest, "defaultLanguageId");
589    
590                    Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
591    
592                    String toLanguageId = ParamUtil.getString(
593                            uploadPortletRequest, "toLanguageId");
594    
595                    Locale toLocale = null;
596    
597                    String title = StringPool.BLANK;
598                    String description = StringPool.BLANK;
599    
600                    if (Validator.isNull(toLanguageId)) {
601                            title = ParamUtil.getString(
602                                    uploadPortletRequest, "title_" + defaultLanguageId);
603                            description = ParamUtil.getString(
604                                    uploadPortletRequest, "description_" + defaultLanguageId);
605                    }
606                    else {
607                            toLocale = LocaleUtil.fromLanguageId(toLanguageId);
608    
609                            title = ParamUtil.getString(
610                                    uploadPortletRequest, "title_" + toLanguageId);
611                            description = ParamUtil.getString(
612                                    uploadPortletRequest, "description_" + toLanguageId);
613                    }
614    
615                    String content = ParamUtil.getString(
616                            uploadPortletRequest, "articleContent");
617    
618                    Map<String, byte[]> images = new HashMap<String, byte[]>();
619    
620                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
621                            JournalArticle.class.getName(), uploadPortletRequest);
622    
623                    String structureId = ParamUtil.getString(
624                            uploadPortletRequest, "structureId");
625    
626                    DDMStructure ddmStructure = null;
627    
628                    if (Validator.isNotNull(structureId)) {
629                            ddmStructure = DDMStructureLocalServiceUtil.getStructure(
630                                    PortalUtil.getSiteGroupId(groupId),
631                                    PortalUtil.getClassNameId(JournalArticle.class), structureId,
632                                    true);
633    
634                            String languageId = toLanguageId;
635    
636                            if (Validator.isNull(languageId)) {
637                                    languageId = defaultLanguageId;
638                            }
639    
640                            Locale locale = LocaleUtil.fromLanguageId(languageId);
641    
642                            Object[] contentAndImages = ActionUtil.getContentAndImages(
643                                    ddmStructure, locale, serviceContext);
644    
645                            content = (String)contentAndImages[0];
646                            images = (HashMap<String, byte[]>)contentAndImages[1];
647                    }
648    
649                    Boolean fileItemThresholdSizeExceeded =
650                            (Boolean)uploadPortletRequest.getAttribute(
651                                    WebKeys.FILE_ITEM_THRESHOLD_SIZE_EXCEEDED);
652    
653                    if ((fileItemThresholdSizeExceeded != null) &&
654                            fileItemThresholdSizeExceeded.booleanValue()) {
655    
656                            throw new ArticleContentSizeException();
657                    }
658    
659                    String type = ParamUtil.getString(uploadPortletRequest, "type");
660                    String templateId = ParamUtil.getString(
661                            uploadPortletRequest, "templateId");
662                    String layoutUuid = ParamUtil.getString(
663                            uploadPortletRequest, "layoutUuid");
664    
665                    // The target page and the article must belong to the same group
666    
667                    Layout targetLayout =
668                            LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
669                                    layoutUuid, groupId, false);
670    
671                    if (targetLayout == null) {
672                            targetLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
673                                    layoutUuid, groupId, true);
674                    }
675    
676                    if (targetLayout == null) {
677                            layoutUuid = null;
678                    }
679    
680                    int displayDateMonth = ParamUtil.getInteger(
681                            uploadPortletRequest, "displayDateMonth");
682                    int displayDateDay = ParamUtil.getInteger(
683                            uploadPortletRequest, "displayDateDay");
684                    int displayDateYear = ParamUtil.getInteger(
685                            uploadPortletRequest, "displayDateYear");
686                    int displayDateHour = ParamUtil.getInteger(
687                            uploadPortletRequest, "displayDateHour");
688                    int displayDateMinute = ParamUtil.getInteger(
689                            uploadPortletRequest, "displayDateMinute");
690                    int displayDateAmPm = ParamUtil.getInteger(
691                            uploadPortletRequest, "displayDateAmPm");
692    
693                    if (displayDateAmPm == Calendar.PM) {
694                            displayDateHour += 12;
695                    }
696    
697                    int expirationDateMonth = ParamUtil.getInteger(
698                            uploadPortletRequest, "expirationDateMonth");
699                    int expirationDateDay = ParamUtil.getInteger(
700                            uploadPortletRequest, "expirationDateDay");
701                    int expirationDateYear = ParamUtil.getInteger(
702                            uploadPortletRequest, "expirationDateYear");
703                    int expirationDateHour = ParamUtil.getInteger(
704                            uploadPortletRequest, "expirationDateHour");
705                    int expirationDateMinute = ParamUtil.getInteger(
706                            uploadPortletRequest, "expirationDateMinute");
707                    int expirationDateAmPm = ParamUtil.getInteger(
708                            uploadPortletRequest, "expirationDateAmPm");
709                    boolean neverExpire = ParamUtil.getBoolean(
710                            uploadPortletRequest, "neverExpire");
711    
712                    if (expirationDateAmPm == Calendar.PM) {
713                            expirationDateHour += 12;
714                    }
715    
716                    int reviewDateMonth = ParamUtil.getInteger(
717                            uploadPortletRequest, "reviewDateMonth");
718                    int reviewDateDay = ParamUtil.getInteger(
719                            uploadPortletRequest, "reviewDateDay");
720                    int reviewDateYear = ParamUtil.getInteger(
721                            uploadPortletRequest, "reviewDateYear");
722                    int reviewDateHour = ParamUtil.getInteger(
723                            uploadPortletRequest, "reviewDateHour");
724                    int reviewDateMinute = ParamUtil.getInteger(
725                            uploadPortletRequest, "reviewDateMinute");
726                    int reviewDateAmPm = ParamUtil.getInteger(
727                            uploadPortletRequest, "reviewDateAmPm");
728                    boolean neverReview = ParamUtil.getBoolean(
729                            uploadPortletRequest, "neverReview");
730    
731                    if (reviewDateAmPm == Calendar.PM) {
732                            reviewDateHour += 12;
733                    }
734    
735                    boolean indexable = ParamUtil.getBoolean(
736                            uploadPortletRequest, "indexable");
737    
738                    boolean smallImage = ParamUtil.getBoolean(
739                            uploadPortletRequest, "smallImage");
740                    String smallImageURL = ParamUtil.getString(
741                            uploadPortletRequest, "smallImageURL");
742                    File smallFile = uploadPortletRequest.getFile("smallFile");
743    
744                    String articleURL = ParamUtil.getString(
745                            uploadPortletRequest, "articleURL");
746    
747                    serviceContext.setAttribute("defaultLanguageId", defaultLanguageId);
748    
749                    JournalArticle article = null;
750                    String oldUrlTitle = StringPool.BLANK;
751    
752                    if (cmd.equals(Constants.ADD)) {
753                            Map<Locale, String> titleMap = new HashMap<Locale, String>();
754    
755                            titleMap.put(defaultLocale, title);
756    
757                            Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
758    
759                            descriptionMap.put(defaultLocale, description);
760    
761                            if (Validator.isNull(structureId)) {
762                                    content = LocalizationUtil.updateLocalization(
763                                            StringPool.BLANK, "static-content", content,
764                                            defaultLanguageId, defaultLanguageId, true, localized);
765                            }
766    
767                            // Add article
768    
769                            article = JournalArticleServiceUtil.addArticle(
770                                    groupId, folderId, classNameId, classPK, articleId,
771                                    autoArticleId, titleMap, descriptionMap, content, type,
772                                    structureId, templateId, layoutUuid, displayDateMonth,
773                                    displayDateDay, displayDateYear, displayDateHour,
774                                    displayDateMinute, expirationDateMonth, expirationDateDay,
775                                    expirationDateYear, expirationDateHour, expirationDateMinute,
776                                    neverExpire, reviewDateMonth, reviewDateDay, reviewDateYear,
777                                    reviewDateHour, reviewDateMinute, neverReview, indexable,
778                                    smallImage, smallImageURL, smallFile, images, articleURL,
779                                    serviceContext);
780    
781                            AssetPublisherUtil.addAndStoreSelection(
782                                    actionRequest, JournalArticle.class.getName(),
783                                    article.getResourcePrimKey(), -1);
784                    }
785                    else {
786    
787                            // Merge current content with new content
788    
789                            JournalArticle curArticle = JournalArticleServiceUtil.getArticle(
790                                    groupId, articleId, version);
791    
792                            if (Validator.isNull(structureId)) {
793                                    if (!curArticle.isTemplateDriven()) {
794                                            String curContent = StringPool.BLANK;
795    
796                                            curContent = curArticle.getContent();
797    
798                                            if (cmd.equals(Constants.TRANSLATE)) {
799                                                    content = LocalizationUtil.updateLocalization(
800                                                            curContent, "static-content", content, toLanguageId,
801                                                            defaultLanguageId, true, true);
802                                            }
803                                            else {
804                                                    content = LocalizationUtil.updateLocalization(
805                                                            curContent, "static-content", content,
806                                                            defaultLanguageId, defaultLanguageId, true,
807                                                            localized);
808                                            }
809                                    }
810                            }
811                            else {
812                                    if (curArticle.isTemplateDriven()) {
813                                            Fields newFields = DDMUtil.getFields(
814                                                    ddmStructure.getStructureId(), serviceContext);
815    
816                                            Fields existingFields = JournalConverterUtil.getDDMFields(
817                                                    ddmStructure, curArticle.getContent());
818    
819                                            Fields mergedFields = DDMUtil.mergeFields(
820                                                    newFields, existingFields);
821    
822                                            content = JournalConverterUtil.getContent(
823                                                    ddmStructure, mergedFields);
824                                    }
825                            }
826    
827                            // Update article
828    
829                            article = JournalArticleServiceUtil.getArticle(
830                                    groupId, articleId, version);
831    
832                            Map<Locale, String> titleMap = article.getTitleMap();
833                            Map<Locale, String> descriptionMap = article.getDescriptionMap();
834    
835                            String tempOldUrlTitle = article.getUrlTitle();
836    
837                            if (cmd.equals(Constants.PREVIEW) || cmd.equals(Constants.UPDATE)) {
838                                    titleMap.put(defaultLocale, title);
839                                    descriptionMap.put(defaultLocale, description);
840    
841                                    article = JournalArticleServiceUtil.updateArticle(
842                                            groupId, folderId, articleId, version, titleMap,
843                                            descriptionMap, content, type, structureId, templateId,
844                                            layoutUuid, displayDateMonth, displayDateDay,
845                                            displayDateYear, displayDateHour, displayDateMinute,
846                                            expirationDateMonth, expirationDateDay, expirationDateYear,
847                                            expirationDateHour, expirationDateMinute, neverExpire,
848                                            reviewDateMonth, reviewDateDay, reviewDateYear,
849                                            reviewDateHour, reviewDateMinute, neverReview, indexable,
850                                            smallImage, smallImageURL, smallFile, images, articleURL,
851                                            serviceContext);
852                            }
853                            else if (cmd.equals(Constants.TRANSLATE)) {
854                                    article = JournalArticleServiceUtil.updateArticleTranslation(
855                                            groupId, articleId, version, toLocale, title, description,
856                                            content, images, serviceContext);
857                            }
858    
859                            if (!tempOldUrlTitle.equals(article.getUrlTitle())) {
860                                    oldUrlTitle = tempOldUrlTitle;
861                            }
862                    }
863    
864                    // Recent articles
865    
866                    JournalUtil.addRecentArticle(actionRequest, article);
867    
868                    // Journal content
869    
870                    PortletPreferences portletPreferences = getStrictPortletSetup(
871                            actionRequest);
872    
873                    if (portletPreferences != null) {
874                            portletPreferences.setValue(
875                                    "groupId", String.valueOf(article.getGroupId()));
876                            portletPreferences.setValue("articleId", article.getArticleId());
877    
878                            portletPreferences.store();
879    
880                            String portletResource = ParamUtil.getString(
881                                    actionRequest, "portletResource");
882    
883                            updateContentSearch(
884                                    actionRequest, portletResource, article.getArticleId());
885                    }
886    
887                    return new Object[] {article, oldUrlTitle};
888            }
889    
890            protected void updateContentSearch(
891                            ActionRequest actionRequest, String portletResource,
892                            String articleId)
893                    throws Exception {
894    
895                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
896                            WebKeys.THEME_DISPLAY);
897    
898                    Layout layout = themeDisplay.getLayout();
899    
900                    JournalContentSearchLocalServiceUtil.updateContentSearch(
901                            layout.getGroupId(), layout.isPrivateLayout(), layout.getLayoutId(),
902                            portletResource, articleId, true);
903            }
904    
905            private static Log _log = LogFactoryUtil.getLog(EditArticleAction.class);
906    
907    }