001    /**
002     * Copyright (c) 2000-2013 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.wiki.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONFactoryUtil;
020    import com.liferay.portal.kernel.json.JSONObject;
021    import com.liferay.portal.kernel.repository.model.FileEntry;
022    import com.liferay.portal.kernel.repository.model.Folder;
023    import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
024    import com.liferay.portal.kernel.search.Indexer;
025    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
026    import com.liferay.portal.kernel.systemevent.SystemEvent;
027    import com.liferay.portal.kernel.systemevent.SystemEventHierarchyEntryThreadLocal;
028    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
029    import com.liferay.portal.kernel.util.ContentTypes;
030    import com.liferay.portal.kernel.util.FileUtil;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.ListUtil;
033    import com.liferay.portal.kernel.util.MathUtil;
034    import com.liferay.portal.kernel.util.MimeTypesUtil;
035    import com.liferay.portal.kernel.util.NotificationThreadLocal;
036    import com.liferay.portal.kernel.util.ObjectValuePair;
037    import com.liferay.portal.kernel.util.OrderByComparator;
038    import com.liferay.portal.kernel.util.StringBundler;
039    import com.liferay.portal.kernel.util.StringPool;
040    import com.liferay.portal.kernel.util.StringUtil;
041    import com.liferay.portal.kernel.util.TempFileUtil;
042    import com.liferay.portal.kernel.util.UnicodeProperties;
043    import com.liferay.portal.kernel.util.UniqueList;
044    import com.liferay.portal.kernel.util.Validator;
045    import com.liferay.portal.kernel.workflow.WorkflowConstants;
046    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
047    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
048    import com.liferay.portal.model.LayoutConstants;
049    import com.liferay.portal.model.ResourceConstants;
050    import com.liferay.portal.model.SystemEventConstants;
051    import com.liferay.portal.model.User;
052    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
053    import com.liferay.portal.service.ServiceContext;
054    import com.liferay.portal.service.ServiceContextUtil;
055    import com.liferay.portal.util.Portal;
056    import com.liferay.portal.util.PortalUtil;
057    import com.liferay.portal.util.PortletKeys;
058    import com.liferay.portal.util.PropsValues;
059    import com.liferay.portal.util.SubscriptionSender;
060    import com.liferay.portlet.PortletURLFactoryUtil;
061    import com.liferay.portlet.asset.model.AssetEntry;
062    import com.liferay.portlet.asset.model.AssetLink;
063    import com.liferay.portlet.asset.model.AssetLinkConstants;
064    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
065    import com.liferay.portlet.expando.model.ExpandoBridge;
066    import com.liferay.portlet.social.model.SocialActivity;
067    import com.liferay.portlet.social.model.SocialActivityConstants;
068    import com.liferay.portlet.trash.model.TrashEntry;
069    import com.liferay.portlet.trash.model.TrashVersion;
070    import com.liferay.portlet.trash.util.TrashUtil;
071    import com.liferay.portlet.wiki.DuplicatePageException;
072    import com.liferay.portlet.wiki.NoSuchPageException;
073    import com.liferay.portlet.wiki.PageContentException;
074    import com.liferay.portlet.wiki.PageTitleException;
075    import com.liferay.portlet.wiki.PageVersionException;
076    import com.liferay.portlet.wiki.model.WikiNode;
077    import com.liferay.portlet.wiki.model.WikiPage;
078    import com.liferay.portlet.wiki.model.WikiPageConstants;
079    import com.liferay.portlet.wiki.model.WikiPageDisplay;
080    import com.liferay.portlet.wiki.model.WikiPageResource;
081    import com.liferay.portlet.wiki.model.impl.WikiPageDisplayImpl;
082    import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
083    import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
084    import com.liferay.portlet.wiki.social.WikiActivityKeys;
085    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
086    import com.liferay.portlet.wiki.util.WikiCacheUtil;
087    import com.liferay.portlet.wiki.util.WikiUtil;
088    import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
089    import com.liferay.portlet.wiki.util.comparator.PageVersionComparator;
090    
091    import java.io.File;
092    import java.io.IOException;
093    import java.io.InputStream;
094    
095    import java.util.ArrayList;
096    import java.util.Calendar;
097    import java.util.Date;
098    import java.util.LinkedHashMap;
099    import java.util.List;
100    import java.util.Map;
101    import java.util.regex.Matcher;
102    import java.util.regex.Pattern;
103    
104    import javax.portlet.PortletPreferences;
105    import javax.portlet.PortletRequest;
106    import javax.portlet.PortletURL;
107    
108    import javax.servlet.http.HttpServletRequest;
109    
110    /**
111     * Provides the local service for accessing, adding, deleting, moving,
112     * subscription handling of, trash handling of, updating, and validating wiki
113     * pages.
114     *
115     * @author Brian Wing Shun Chan
116     * @author Jorge Ferrer
117     * @author Raymond Aug??
118     * @author Bruno Farache
119     * @author Julio Camarero
120     * @author Wesley Gong
121     * @author Marcellus Tavares
122     * @author Zsigmond Rab
123     * @author Zsolt Berentey
124     */
125    public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
126    
127            @Override
128            public WikiPage addPage(
129                            long userId, long nodeId, String title, double version,
130                            String content, String summary, boolean minorEdit, String format,
131                            boolean head, String parentTitle, String redirectTitle,
132                            ServiceContext serviceContext)
133                    throws PortalException, SystemException {
134    
135                    // Page
136    
137                    User user = userPersistence.findByPrimaryKey(userId);
138                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
139                    Date now = new Date();
140    
141                    long pageId = counterLocalService.increment();
142    
143                    content = SanitizerUtil.sanitize(
144                            user.getCompanyId(), node.getGroupId(), userId,
145                            WikiPage.class.getName(), pageId, "text/" + format, content);
146    
147                    validate(title, nodeId, content, format);
148    
149                    long resourcePrimKey =
150                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
151    
152                    WikiPage page = wikiPagePersistence.create(pageId);
153    
154                    page.setUuid(serviceContext.getUuid());
155                    page.setResourcePrimKey(resourcePrimKey);
156                    page.setGroupId(node.getGroupId());
157                    page.setCompanyId(user.getCompanyId());
158                    page.setUserId(user.getUserId());
159                    page.setUserName(user.getFullName());
160                    page.setCreateDate(serviceContext.getCreateDate(now));
161                    page.setModifiedDate(serviceContext.getModifiedDate(now));
162                    page.setNodeId(nodeId);
163                    page.setTitle(title);
164                    page.setVersion(version);
165                    page.setMinorEdit(minorEdit);
166                    page.setContent(content);
167                    page.setSummary(summary);
168                    page.setFormat(format);
169                    page.setHead(head);
170                    page.setParentTitle(parentTitle);
171                    page.setRedirectTitle(redirectTitle);
172                    page.setStatus(WorkflowConstants.STATUS_DRAFT);
173                    page.setStatusByUserId(userId);
174                    page.setStatusDate(serviceContext.getModifiedDate(now));
175                    page.setExpandoBridgeAttributes(serviceContext);
176    
177                    wikiPagePersistence.update(page);
178    
179                    // Resources
180    
181                    if (serviceContext.isAddGroupPermissions() ||
182                            serviceContext.isAddGuestPermissions()) {
183    
184                            addPageResources(
185                                    page, serviceContext.isAddGroupPermissions(),
186                                    serviceContext.isAddGuestPermissions());
187                    }
188                    else {
189                            addPageResources(
190                                    page, serviceContext.getGroupPermissions(),
191                                    serviceContext.getGuestPermissions());
192                    }
193    
194                    // Node
195    
196                    node.setLastPostDate(serviceContext.getModifiedDate(now));
197    
198                    wikiNodePersistence.update(node);
199    
200                    // Asset
201    
202                    updateAsset(
203                            userId, page, serviceContext.getAssetCategoryIds(),
204                            serviceContext.getAssetTagNames(),
205                            serviceContext.getAssetLinkEntryIds());
206    
207                    // Message boards
208    
209                    if (PropsValues.WIKI_PAGE_COMMENTS_ENABLED) {
210                            mbMessageLocalService.addDiscussionMessage(
211                                    userId, page.getUserName(), page.getGroupId(),
212                                    WikiPage.class.getName(), resourcePrimKey,
213                                    WorkflowConstants.ACTION_PUBLISH);
214                    }
215    
216                    // Workflow
217    
218                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
219                            user.getCompanyId(), page.getGroupId(), userId,
220                            WikiPage.class.getName(), page.getPageId(), page, serviceContext);
221    
222                    return page;
223            }
224    
225            @Override
226            public WikiPage addPage(
227                            long userId, long nodeId, String title, String content,
228                            String summary, boolean minorEdit, ServiceContext serviceContext)
229                    throws PortalException, SystemException {
230    
231                    double version = WikiPageConstants.VERSION_DEFAULT;
232                    String format = WikiPageConstants.DEFAULT_FORMAT;
233                    boolean head = false;
234                    String parentTitle = null;
235                    String redirectTitle = null;
236    
237                    return addPage(
238                            userId, nodeId, title, version, content, summary, minorEdit, format,
239                            head, parentTitle, redirectTitle, serviceContext);
240            }
241    
242            @Override
243            public void addPageAttachment(
244                            long userId, long nodeId, String title, String fileName, File file,
245                            String mimeType)
246                    throws PortalException, SystemException {
247    
248                    WikiPage page = getPage(nodeId, title);
249    
250                    Folder folder = page.addAttachmentsFolder();
251    
252                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
253                            page.getGroupId(), userId, WikiPage.class.getName(),
254                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
255                            file, fileName, mimeType, true);
256    
257                    if (userId == 0) {
258                            userId = page.getUserId();
259                    }
260    
261                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
262    
263                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
264                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
265                    extraDataJSONObject.put("title", page.getTitle());
266                    extraDataJSONObject.put("version", page.getVersion());
267    
268                    socialActivityLocalService.addActivity(
269                            userId, page.getGroupId(), WikiPage.class.getName(),
270                            page.getResourcePrimKey(),
271                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
272                            extraDataJSONObject.toString(), 0);
273            }
274    
275            @Override
276            public void addPageAttachment(
277                            long userId, long nodeId, String title, String fileName,
278                            InputStream inputStream, String mimeType)
279                    throws PortalException, SystemException {
280    
281                    WikiPage page = getPage(nodeId, title);
282    
283                    Folder folder = page.addAttachmentsFolder();
284    
285                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
286                            page.getGroupId(), userId, WikiPage.class.getName(),
287                            page.getResourcePrimKey(), PortletKeys.WIKI, folder.getFolderId(),
288                            inputStream, fileName, mimeType, true);
289    
290                    if (userId == 0) {
291                            userId = page.getUserId();
292                    }
293    
294                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
295    
296                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
297                    extraDataJSONObject.put("fileEntryTitle", fileEntry.getTitle());
298                    extraDataJSONObject.put("title", page.getTitle());
299                    extraDataJSONObject.put("version", page.getVersion());
300    
301                    socialActivityLocalService.addActivity(
302                            userId, page.getGroupId(), WikiPage.class.getName(),
303                            page.getResourcePrimKey(),
304                            SocialActivityConstants.TYPE_ADD_ATTACHMENT,
305                            extraDataJSONObject.toString(), 0);
306            }
307    
308            @Override
309            public void addPageAttachments(
310                            long userId, long nodeId, String title,
311                            List<ObjectValuePair<String, InputStream>> inputStreamOVPs)
312                    throws PortalException, SystemException {
313    
314                    if (inputStreamOVPs.size() == 0) {
315                            return;
316                    }
317    
318                    for (int i = 0; i < inputStreamOVPs.size(); i++) {
319                            ObjectValuePair<String, InputStream> inputStreamOVP =
320                                    inputStreamOVPs.get(i);
321    
322                            String fileName = inputStreamOVP.getKey();
323                            InputStream inputStream = inputStreamOVP.getValue();
324    
325                            File file = null;
326    
327                            try {
328                                    file = FileUtil.createTempFile(inputStream);
329    
330                                    String mimeType = MimeTypesUtil.getContentType(file, fileName);
331    
332                                    addPageAttachment(
333                                            userId, nodeId, title, fileName, file, mimeType);
334                            }
335                            catch (IOException ioe) {
336                                    throw new SystemException(
337                                            "Unable to write temporary file", ioe);
338                            }
339                            finally {
340                                    FileUtil.delete(file);
341                            }
342                    }
343            }
344    
345            @Override
346            public void addPageResources(
347                            long nodeId, String title, boolean addGroupPermissions,
348                            boolean addGuestPermissions)
349                    throws PortalException, SystemException {
350    
351                    WikiPage page = getPage(nodeId, title);
352    
353                    addPageResources(page, addGroupPermissions, addGuestPermissions);
354            }
355    
356            @Override
357            public void addPageResources(
358                            long nodeId, String title, String[] groupPermissions,
359                            String[] guestPermissions)
360                    throws PortalException, SystemException {
361    
362                    WikiPage page = getPage(nodeId, title);
363    
364                    addPageResources(page, groupPermissions, guestPermissions);
365            }
366    
367            @Override
368            public void addPageResources(
369                            WikiPage page, boolean addGroupPermissions,
370                            boolean addGuestPermissions)
371                    throws PortalException, SystemException {
372    
373                    resourceLocalService.addResources(
374                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
375                            WikiPage.class.getName(), page.getResourcePrimKey(), false,
376                            addGroupPermissions, addGuestPermissions);
377            }
378    
379            @Override
380            public void addPageResources(
381                            WikiPage page, String[] groupPermissions, String[] guestPermissions)
382                    throws PortalException, SystemException {
383    
384                    resourceLocalService.addModelResources(
385                            page.getCompanyId(), page.getGroupId(), page.getUserId(),
386                            WikiPage.class.getName(), page.getResourcePrimKey(),
387                            groupPermissions, guestPermissions);
388            }
389    
390            @Override
391            public void addTempPageAttachment(
392                            long groupId, long userId, String fileName, String tempFolderName,
393                            InputStream inputStream, String mimeType)
394                    throws PortalException, SystemException {
395    
396                    TempFileUtil.addTempFile(
397                            groupId, userId, fileName, tempFolderName, inputStream, mimeType);
398            }
399    
400            @Override
401            public void changeParent(
402                            long userId, long nodeId, String title, String newParentTitle,
403                            ServiceContext serviceContext)
404                    throws PortalException, SystemException {
405    
406                    if (Validator.isNotNull(newParentTitle)) {
407                            WikiPage parentPage = getPage(nodeId, newParentTitle);
408    
409                            if (Validator.isNotNull(parentPage.getRedirectTitle())) {
410                                    newParentTitle = parentPage.getRedirectTitle();
411                            }
412                    }
413    
414                    WikiPage page = getPage(nodeId, title);
415    
416                    String originalParentTitle = page.getParentTitle();
417    
418                    double version = page.getVersion();
419                    String content = page.getContent();
420                    String summary = serviceContext.translate(
421                            "changed-parent-from-x", originalParentTitle);
422                    boolean minorEdit = false;
423                    String format = page.getFormat();
424                    String redirectTitle = page.getRedirectTitle();
425    
426                    populateServiceContext(serviceContext, page);
427    
428                    updatePage(
429                            userId, nodeId, title, version, content, summary, minorEdit, format,
430                            newParentTitle, redirectTitle, serviceContext);
431    
432                    List<WikiPage> oldPages = wikiPagePersistence.findByN_T_H(
433                            nodeId, title, false);
434    
435                    for (WikiPage oldPage : oldPages) {
436                            if (!WorkflowThreadLocal.isEnabled()) {
437                                    oldPage.setParentTitle(originalParentTitle);
438    
439                                    wikiPagePersistence.update(oldPage);
440                            }
441                    }
442            }
443    
444            @Override
445            public void copyPageAttachments(
446                            long userId, long templateNodeId, String templateTitle, long nodeId,
447                            String title)
448                    throws PortalException, SystemException {
449    
450                    WikiPage templatePage = getPage(templateNodeId, templateTitle);
451    
452                    List<FileEntry> templateFileEntries =
453                            templatePage.getAttachmentsFileEntries();
454    
455                    for (FileEntry templateFileEntry : templateFileEntries) {
456                            addPageAttachment(
457                                    userId, nodeId, title, templateFileEntry.getTitle(),
458                                    templateFileEntry.getContentStream(),
459                                    templateFileEntry.getMimeType());
460                    }
461            }
462    
463            @Override
464            public void deletePage(long nodeId, String title)
465                    throws PortalException, SystemException {
466    
467                    List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
468                            nodeId, title, true, 0, 1);
469    
470                    if (!pages.isEmpty()) {
471                            wikiPageLocalService.deletePage(pages.get(0));
472                    }
473            }
474    
475            /**
476             * @deprecated As of 6.2.0 replaced by {@link #discardDraft(long, String,
477             *             double)}
478             */
479            @Override
480            public void deletePage(long nodeId, String title, double version)
481                    throws PortalException, SystemException {
482    
483                    discardDraft(nodeId, title, version);
484            }
485    
486            @Override
487            @SystemEvent(
488                    action = SystemEventConstants.ACTION_SKIP, send = false,
489                    type = SystemEventConstants.TYPE_DELETE)
490            public void deletePage(WikiPage page)
491                    throws PortalException, SystemException {
492    
493                    // Children
494    
495                    List<WikiPage> childrenPages = wikiPagePersistence.findByN_P(
496                            page.getNodeId(), page.getTitle());
497    
498                    for (WikiPage childrenPage : childrenPages) {
499                            if (!childrenPage.isApproved()) {
500                                    childrenPage.setParentTitle(StringPool.BLANK);
501    
502                                    wikiPagePersistence.update(childrenPage);
503                            }
504                            else {
505                                    wikiPageLocalService.deletePage(childrenPage);
506                            }
507                    }
508    
509                    // Redirect Pages
510    
511                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_R(
512                            page.getNodeId(), page.getTitle());
513    
514                    for (WikiPage redirectPage : redirectPages) {
515                            if (!redirectPage.isApproved()) {
516                                    redirectPage.setRedirectTitle(StringPool.BLANK);
517    
518                                    wikiPagePersistence.update(redirectPage);
519                            }
520                            else {
521                                    wikiPageLocalService.deletePage(redirectPage);
522                            }
523                    }
524    
525                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
526                            page.getNodeId(), page.getTitle());
527    
528                    wikiPagePersistence.removeByN_T(page.getNodeId(), page.getTitle());
529    
530                    // References
531    
532                    wikiPagePersistence.removeByN_R(page.getNodeId(), page.getTitle());
533    
534                    // Resources
535    
536                    resourceLocalService.deleteResource(
537                            page.getCompanyId(), WikiPage.class.getName(),
538                            ResourceConstants.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
539    
540                    // Resource
541    
542                    WikiPageResource pageResource =
543                            wikiPageResourceLocalService.fetchPageResource(
544                                    page.getNodeId(), page.getTitle());
545    
546                    if (pageResource != null) {
547                            wikiPageResourceLocalService.deleteWikiPageResource(pageResource);
548                    }
549    
550                    // Attachments
551    
552                    long folderId = page.getAttachmentsFolderId();
553    
554                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
555                            PortletFileRepositoryUtil.deleteFolder(folderId);
556                    }
557    
558                    // Subscriptions
559    
560                    subscriptionLocalService.deleteSubscriptions(
561                            page.getCompanyId(), WikiPage.class.getName(),
562                            page.getResourcePrimKey());
563    
564                    // Asset
565    
566                    SystemEventHierarchyEntryThreadLocal.pop(
567                            page.getModelClass(), page.getPageId());
568    
569                    try {
570                            for (WikiPage versionPage : versionPages) {
571                                    assetEntryLocalService.deleteEntry(
572                                            WikiPage.class.getName(), versionPage.getPrimaryKey());
573                            }
574                    }
575                    finally {
576                            SystemEventHierarchyEntryThreadLocal.push(
577                                    page.getModelClass(), page.getPageId());
578                    }
579    
580                    assetEntryLocalService.deleteEntry(
581                            WikiPage.class.getName(), page.getResourcePrimKey());
582    
583                    // Expando
584    
585                    expandoRowLocalService.deleteRows(page.getPrimaryKey());
586    
587                    // Message boards
588    
589                    mbMessageLocalService.deleteDiscussionMessages(
590                            WikiPage.class.getName(), page.getResourcePrimKey());
591    
592                    // Trash
593    
594                    if (page.isInTrash()) {
595                            page.setTitle(TrashUtil.getOriginalTitle(page.getTitle()));
596    
597                            trashEntryLocalService.deleteEntry(
598                                    WikiPage.class.getName(), page.getResourcePrimKey());
599                    }
600    
601                    // Indexer
602    
603                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
604                            WikiPage.class);
605    
606                    indexer.delete(page);
607    
608                    // Cache
609    
610                    clearPageCache(page);
611    
612                    // All versions
613    
614                    for (WikiPage versionPage : versionPages) {
615    
616                            // Workflow
617    
618                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
619                                    versionPage.getCompanyId(), versionPage.getGroupId(),
620                                    WikiPage.class.getName(), versionPage.getPageId());
621                    }
622    
623                    if (pageResource != null) {
624                            JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
625    
626                            extraDataJSONObject.put("version", page.getVersion());
627    
628                            systemEventLocalService.addSystemEvent(
629                                    0, page.getGroupId(), page.getModelClassName(),
630                                    page.getPrimaryKey(), pageResource.getUuid(), null,
631                                    SystemEventConstants.TYPE_DELETE,
632                                    extraDataJSONObject.toString());
633                    }
634            }
635    
636            @Override
637            public void deletePageAttachment(long nodeId, String title, String fileName)
638                    throws PortalException, SystemException {
639    
640                    WikiPage page = getPage(nodeId, title);
641    
642                    long folderId = page.getAttachmentsFolderId();
643    
644                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
645                            return;
646                    }
647    
648                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
649                            page.getGroupId(), folderId, fileName);
650    
651                    deletePageAttachment(fileEntry.getFileEntryId());
652            }
653    
654            @Override
655            public void deletePageAttachments(long nodeId, String title)
656                    throws PortalException, SystemException {
657    
658                    WikiPage page = getPage(nodeId, title);
659    
660                    long folderId = page.getAttachmentsFolderId();
661    
662                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
663                            return;
664                    }
665    
666                    PortletFileRepositoryUtil.deletePortletFileEntries(
667                            page.getGroupId(), folderId);
668            }
669    
670            @Override
671            public void deletePages(long nodeId)
672                    throws PortalException, SystemException {
673    
674                    List<WikiPage> pages = wikiPagePersistence.findByN_H_P(
675                            nodeId, true, StringPool.BLANK);
676    
677                    for (WikiPage page : pages) {
678                            wikiPageLocalService.deletePage(page);
679                    }
680    
681                    pages = wikiPagePersistence.findByN_H_P(
682                            nodeId, false, StringPool.BLANK);
683    
684                    for (WikiPage page : pages) {
685                            wikiPageLocalService.deletePage(page);
686                    }
687            }
688    
689            @Override
690            public void deleteTempPageAttachment(
691                            long groupId, long userId, String fileName, String tempFolderName)
692                    throws PortalException, SystemException {
693    
694                    TempFileUtil.deleteTempFile(groupId, userId, fileName, tempFolderName);
695            }
696    
697            @Override
698            public void deleteTrashPageAttachments(long nodeId, String title)
699                    throws PortalException, SystemException {
700    
701                    WikiPage page = getPage(nodeId, title);
702    
703                    long folderId = page.getAttachmentsFolderId();
704    
705                    if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
706                            return;
707                    }
708    
709                    PortletFileRepositoryUtil.deletePortletFileEntries(
710                            page.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH);
711            }
712    
713            @Override
714            public void discardDraft(long nodeId, String title, double version)
715                    throws PortalException, SystemException {
716    
717                    wikiPagePersistence.removeByN_T_V(nodeId, title, version);
718            }
719    
720            @Override
721            public WikiPage fetchLatestPage(
722                            long resourcePrimKey, int status, boolean preferApproved)
723                    throws SystemException {
724    
725                    WikiPage page = null;
726    
727                    OrderByComparator orderByComparator = new PageVersionComparator();
728    
729                    if (status == WorkflowConstants.STATUS_ANY) {
730                            if (preferApproved) {
731                                    page = wikiPagePersistence.fetchByR_S_First(
732                                            resourcePrimKey, WorkflowConstants.STATUS_APPROVED,
733                                            orderByComparator);
734                            }
735    
736                            if (page == null) {
737                                    page = wikiPagePersistence.fetchByResourcePrimKey_First(
738                                            resourcePrimKey, orderByComparator);
739                            }
740                    }
741                    else {
742                            page = wikiPagePersistence.fetchByR_S_First(
743                                    resourcePrimKey, status, orderByComparator);
744                    }
745    
746                    return page;
747            }
748    
749            @Override
750            public WikiPage fetchLatestPage(
751                            long resourcePrimKey, long nodeId, int status,
752                            boolean preferApproved)
753                    throws SystemException {
754    
755                    WikiPage page = null;
756    
757                    OrderByComparator orderByComparator = new PageVersionComparator();
758    
759                    if (status == WorkflowConstants.STATUS_ANY) {
760                            if (preferApproved) {
761                                    page = wikiPagePersistence.fetchByR_N_S_First(
762                                            resourcePrimKey, nodeId, WorkflowConstants.STATUS_APPROVED,
763                                            orderByComparator);
764                            }
765    
766                            if (page == null) {
767                                    page = wikiPagePersistence.fetchByR_N_First(
768                                            resourcePrimKey, nodeId, orderByComparator);
769                            }
770                    }
771                    else {
772                            page = wikiPagePersistence.fetchByR_N_S_First(
773                                    resourcePrimKey, nodeId, status, orderByComparator);
774                    }
775    
776                    return page;
777            }
778    
779            @Override
780            public WikiPage fetchLatestPage(
781                            long nodeId, String title, int status, boolean preferApproved)
782                    throws SystemException {
783    
784                    WikiPage page = null;
785    
786                    OrderByComparator orderByComparator = new PageVersionComparator();
787    
788                    if (status == WorkflowConstants.STATUS_ANY) {
789                            if (preferApproved) {
790                                    page = wikiPagePersistence.fetchByN_T_S_First(
791                                            nodeId, title, WorkflowConstants.STATUS_APPROVED,
792                                            orderByComparator);
793                            }
794    
795                            if (page == null) {
796                                    page = wikiPagePersistence.fetchByN_T_First(
797                                            nodeId, title, orderByComparator);
798                            }
799                    }
800                    else {
801                            page = wikiPagePersistence.fetchByN_T_S_First(
802                                    nodeId, title, status, orderByComparator);
803                    }
804    
805                    return page;
806            }
807    
808            @Override
809            public WikiPage fetchPage(long nodeId, String title)
810                    throws SystemException {
811    
812                    return wikiPagePersistence.fetchByN_T_H_First(
813                            nodeId, title, true, null);
814            }
815    
816            @Override
817            public WikiPage fetchPage(long nodeId, String title, double version)
818                    throws SystemException {
819    
820                    if (version == 0) {
821                            return fetchPage(nodeId, title);
822                    }
823                    else {
824                            return wikiPagePersistence.fetchByN_T_V(nodeId, title, version);
825                    }
826            }
827    
828            @Override
829            public List<WikiPage> getChildren(
830                            long nodeId, boolean head, String parentTitle)
831                    throws SystemException {
832    
833                    return wikiPagePersistence.findByN_H_P_S(
834                            nodeId, head, parentTitle, WorkflowConstants.STATUS_APPROVED);
835            }
836    
837            @Override
838            public WikiPage getDraftPage(long nodeId, String title)
839                    throws PortalException, SystemException {
840    
841                    List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
842                            nodeId, title, WorkflowConstants.STATUS_DRAFT, 0, 1);
843    
844                    if (!pages.isEmpty()) {
845                            return pages.get(0);
846                    }
847    
848                    pages = wikiPagePersistence.findByN_T_S(
849                            nodeId, title, WorkflowConstants.STATUS_PENDING, 0, 1);
850    
851                    if (!pages.isEmpty()) {
852                            return pages.get(0);
853                    }
854                    else {
855                            StringBundler sb = new StringBundler(5);
856    
857                            sb.append("{nodeId=");
858                            sb.append(nodeId);
859                            sb.append(", title=");
860                            sb.append(title);
861                            sb.append("}");
862    
863                            throw new NoSuchPageException(sb.toString());
864                    }
865            }
866    
867            @Override
868            public List<WikiPage> getIncomingLinks(long nodeId, String title)
869                    throws PortalException, SystemException {
870    
871                    List<WikiPage> links = new UniqueList<WikiPage>();
872    
873                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
874    
875                    for (WikiPage page : pages) {
876                            if (isLinkedTo(page, title)) {
877                                    links.add(page);
878                            }
879                    }
880    
881                    List<WikiPage> referrals = wikiPagePersistence.findByN_R(nodeId, title);
882    
883                    for (WikiPage referral : referrals) {
884                            for (WikiPage page : pages) {
885                                    if (isLinkedTo(page, referral.getTitle())) {
886                                            links.add(page);
887                                    }
888                            }
889                    }
890    
891                    return ListUtil.sort(links);
892            }
893    
894            @Override
895            public WikiPage getLatestPage(
896                            long resourcePrimKey, int status, boolean preferApproved)
897                    throws PortalException, SystemException {
898    
899                    WikiPage page = fetchLatestPage(
900                            resourcePrimKey, status, preferApproved);
901    
902                    if (page == null) {
903                            StringBundler sb = new StringBundler(5);
904    
905                            sb.append("{resourcePrimKey=");
906                            sb.append(resourcePrimKey);
907                            sb.append(", status=");
908                            sb.append(status);
909                            sb.append("}");
910    
911                            throw new NoSuchPageException(sb.toString());
912                    }
913    
914                    return page;
915            }
916    
917            @Override
918            public WikiPage getLatestPage(
919                            long resourcePrimKey, long nodeId, int status,
920                            boolean preferApproved)
921                    throws PortalException, SystemException {
922    
923                    WikiPage page = fetchLatestPage(
924                            resourcePrimKey, nodeId, status, preferApproved);
925    
926                    if (page == null) {
927                            StringBundler sb = new StringBundler(7);
928    
929                            sb.append("{resourcePrimKey=");
930                            sb.append(resourcePrimKey);
931                            sb.append(", nodeId=");
932                            sb.append(nodeId);
933                            sb.append(", status=");
934                            sb.append(status);
935                            sb.append("}");
936    
937                            throw new NoSuchPageException(sb.toString());
938                    }
939    
940                    return page;
941            }
942    
943            @Override
944            public WikiPage getLatestPage(
945                            long nodeId, String title, int status, boolean preferApproved)
946                    throws PortalException, SystemException {
947    
948                    WikiPage page = fetchLatestPage(nodeId, title, status, preferApproved);
949    
950                    if (page == null) {
951                            StringBundler sb = new StringBundler(7);
952    
953                            sb.append("{nodeId=");
954                            sb.append(nodeId);
955                            sb.append(", title=");
956                            sb.append(title);
957                            sb.append(", status=");
958                            sb.append(status);
959                            sb.append("}");
960    
961                            throw new NoSuchPageException(sb.toString());
962                    }
963    
964                    return page;
965            }
966    
967            @Override
968            public List<WikiPage> getNoAssetPages() throws SystemException {
969                    return wikiPageFinder.findByNoAssets();
970            }
971    
972            @Override
973            public List<WikiPage> getOrphans(long nodeId)
974                    throws PortalException, SystemException {
975    
976                    List<WikiPage> pages = wikiPagePersistence.findByN_H_S(
977                            nodeId, true, WorkflowConstants.STATUS_APPROVED);
978    
979                    return WikiUtil.filterOrphans(pages);
980            }
981    
982            @Override
983            public List<WikiPage> getOutgoingLinks(long nodeId, String title)
984                    throws PortalException, SystemException {
985    
986                    WikiPage page = getPage(nodeId, title);
987    
988                    Map<String, WikiPage> pages = new LinkedHashMap<String, WikiPage>();
989    
990                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
991    
992                    for (Map.Entry<String, Boolean> entry : links.entrySet()) {
993                            String curTitle = entry.getKey();
994                            Boolean exists = entry.getValue();
995    
996                            if (exists) {
997                                    WikiPage curPage = getPage(nodeId, curTitle);
998    
999                                    if (!pages.containsKey(curPage.getTitle())) {
1000                                            pages.put(curPage.getTitle(), curPage);
1001                                    }
1002                            }
1003                            else {
1004                                    WikiPageImpl newPage = new WikiPageImpl();
1005    
1006                                    newPage.setNew(true);
1007                                    newPage.setNodeId(nodeId);
1008                                    newPage.setTitle(curTitle);
1009    
1010                                    if (!pages.containsKey(curTitle)) {
1011                                            pages.put(curTitle, newPage);
1012                                    }
1013                            }
1014                    }
1015    
1016                    return ListUtil.fromMapValues(pages);
1017            }
1018    
1019            @Override
1020            public WikiPage getPage(long resourcePrimKey)
1021                    throws PortalException, SystemException {
1022    
1023                    return getPage(resourcePrimKey, Boolean.TRUE);
1024            }
1025    
1026            @Override
1027            public WikiPage getPage(long resourcePrimKey, Boolean head)
1028                    throws PortalException, SystemException {
1029    
1030                    WikiPageResource pageResource =
1031                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
1032    
1033                    return getPage(pageResource.getNodeId(), pageResource.getTitle(), head);
1034            }
1035    
1036            @Override
1037            public WikiPage getPage(long nodeId, String title)
1038                    throws PortalException, SystemException {
1039    
1040                    WikiPage page = fetchPage(nodeId, title);
1041    
1042                    if (page != null) {
1043                            return page;
1044                    }
1045                    else {
1046                            StringBundler sb = new StringBundler(5);
1047    
1048                            sb.append("{nodeId=");
1049                            sb.append(nodeId);
1050                            sb.append(", title=");
1051                            sb.append(title);
1052                            sb.append("}");
1053    
1054                            throw new NoSuchPageException(sb.toString());
1055                    }
1056            }
1057    
1058            @Override
1059            public WikiPage getPage(long nodeId, String title, Boolean head)
1060                    throws PortalException, SystemException {
1061    
1062                    List<WikiPage> pages;
1063    
1064                    if (head == null) {
1065                            pages = wikiPagePersistence.findByN_T(nodeId, title, 0, 1);
1066                    }
1067                    else {
1068                            pages = wikiPagePersistence.findByN_T_H(nodeId, title, head, 0, 1);
1069                    }
1070    
1071                    if (!pages.isEmpty()) {
1072                            return pages.get(0);
1073                    }
1074                    else {
1075                            StringBundler sb = new StringBundler(7);
1076    
1077                            sb.append("{nodeId=");
1078                            sb.append(nodeId);
1079                            sb.append(", title=");
1080                            sb.append(title);
1081                            sb.append(", head=");
1082                            sb.append(head);
1083                            sb.append("}");
1084    
1085                            throw new NoSuchPageException(sb.toString());
1086                    }
1087            }
1088    
1089            @Override
1090            public WikiPage getPage(long nodeId, String title, double version)
1091                    throws PortalException, SystemException {
1092    
1093                    WikiPage page = null;
1094    
1095                    if (version == 0) {
1096                            page = getPage(nodeId, title);
1097                    }
1098                    else {
1099                            page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1100                    }
1101    
1102                    return page;
1103            }
1104    
1105            @Override
1106            public WikiPage getPageByPageId(long pageId)
1107                    throws PortalException, SystemException {
1108    
1109                    return wikiPagePersistence.findByPrimaryKey(pageId);
1110            }
1111    
1112            @Override
1113            public WikiPageDisplay getPageDisplay(
1114                            long nodeId, String title, PortletURL viewPageURL,
1115                            PortletURL editPageURL, String attachmentURLPrefix)
1116                    throws PortalException, SystemException {
1117    
1118                    WikiPage page = getPage(nodeId, title);
1119    
1120                    return getPageDisplay(
1121                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1122            }
1123    
1124            @Override
1125            public WikiPageDisplay getPageDisplay(
1126                            WikiPage page, PortletURL viewPageURL, PortletURL editPageURL,
1127                            String attachmentURLPrefix)
1128                    throws PortalException, SystemException {
1129    
1130                    String formattedContent = WikiUtil.convert(
1131                            page, viewPageURL, editPageURL, attachmentURLPrefix);
1132    
1133                    return new WikiPageDisplayImpl(
1134                            page.getUserId(), page.getNodeId(), page.getTitle(),
1135                            page.getVersion(), page.getContent(), formattedContent,
1136                            page.getFormat(), page.getHead(), page.getAttachmentsFileEntries());
1137            }
1138    
1139            @Override
1140            public List<WikiPage> getPages(
1141                            long nodeId, boolean head, int start, int end)
1142                    throws SystemException {
1143    
1144                    return getPages(
1145                            nodeId, head, start, end, new PageCreateDateComparator(false));
1146            }
1147    
1148            @Override
1149            public List<WikiPage> getPages(
1150                            long nodeId, boolean head, int status, int start, int end)
1151                    throws SystemException {
1152    
1153                    return getPages(
1154                            nodeId, head, status, start, end,
1155                            new PageCreateDateComparator(false));
1156            }
1157    
1158            @Override
1159            public List<WikiPage> getPages(
1160                            long nodeId, boolean head, int status, int start, int end,
1161                            OrderByComparator obc)
1162                    throws SystemException {
1163    
1164                    if (status == WorkflowConstants.STATUS_ANY) {
1165                            return wikiPagePersistence.findByN_H(nodeId, head, start, end, obc);
1166                    }
1167                    else {
1168                            return wikiPagePersistence.findByN_H_S(
1169                                    nodeId, head, status, start, end, obc);
1170                    }
1171            }
1172    
1173            @Override
1174            public List<WikiPage> getPages(
1175                            long nodeId, boolean head, int start, int end,
1176                            OrderByComparator obc)
1177                    throws SystemException {
1178    
1179                    return getPages(
1180                            nodeId, head, WorkflowConstants.STATUS_APPROVED, start, end, obc);
1181            }
1182    
1183            @Override
1184            public List<WikiPage> getPages(long nodeId, int start, int end)
1185                    throws SystemException {
1186    
1187                    return getPages(
1188                            nodeId, start, end, new PageCreateDateComparator(false));
1189            }
1190    
1191            @Override
1192            public List<WikiPage> getPages(
1193                            long nodeId, int start, int end, OrderByComparator obc)
1194                    throws SystemException {
1195    
1196                    return wikiPagePersistence.findByNodeId(nodeId, start, end, obc);
1197            }
1198    
1199            @Override
1200            public List<WikiPage> getPages(
1201                            long resourcePrimKey, long nodeId, int status)
1202                    throws SystemException {
1203    
1204                    return wikiPagePersistence.findByR_N_S(resourcePrimKey, nodeId, status);
1205            }
1206    
1207            @Override
1208            public List<WikiPage> getPages(
1209                            long userId, long nodeId, int status, int start, int end)
1210                    throws SystemException {
1211    
1212                    if (userId > 0) {
1213                            return wikiPagePersistence.findByU_N_S(
1214                                    userId, nodeId, status, start, end,
1215                                    new PageCreateDateComparator(false));
1216                    }
1217                    else {
1218                            return wikiPagePersistence.findByN_S(
1219                                    nodeId, status, start, end,
1220                                    new PageCreateDateComparator(false));
1221                    }
1222            }
1223    
1224            @Override
1225            public List<WikiPage> getPages(
1226                            long nodeId, String title, boolean head, int start, int end)
1227                    throws SystemException {
1228    
1229                    return wikiPagePersistence.findByN_T_H(
1230                            nodeId, title, head, start, end,
1231                            new PageCreateDateComparator(false));
1232            }
1233    
1234            @Override
1235            public List<WikiPage> getPages(
1236                            long nodeId, String title, int start, int end)
1237                    throws SystemException {
1238    
1239                    return wikiPagePersistence.findByN_T(
1240                            nodeId, title, start, end, new PageCreateDateComparator(false));
1241            }
1242    
1243            @Override
1244            public List<WikiPage> getPages(
1245                            long nodeId, String title, int start, int end,
1246                            OrderByComparator obc)
1247                    throws SystemException {
1248    
1249                    return wikiPagePersistence.findByN_T(nodeId, title, start, end, obc);
1250            }
1251    
1252            @Override
1253            public List<WikiPage> getPages(String format) throws SystemException {
1254                    return wikiPagePersistence.findByFormat(format);
1255            }
1256    
1257            @Override
1258            public int getPagesCount(long nodeId) throws SystemException {
1259                    return wikiPagePersistence.countByNodeId(nodeId);
1260            }
1261    
1262            @Override
1263            public int getPagesCount(long nodeId, boolean head) throws SystemException {
1264                    return wikiPagePersistence.countByN_H_S(
1265                            nodeId, head, WorkflowConstants.STATUS_APPROVED);
1266            }
1267    
1268            @Override
1269            public int getPagesCount(long nodeId, boolean head, int status)
1270                    throws SystemException {
1271    
1272                    if (status == WorkflowConstants.STATUS_ANY) {
1273                            return wikiPagePersistence.countByN_H_NotS(
1274                                    nodeId, head, WorkflowConstants.STATUS_IN_TRASH);
1275                    }
1276                    else {
1277                            return wikiPagePersistence.countByN_H_S(nodeId, head, status);
1278                    }
1279            }
1280    
1281            @Override
1282            public int getPagesCount(long nodeId, int status) throws SystemException {
1283                    return wikiPagePersistence.countByN_S(nodeId, status);
1284            }
1285    
1286            @Override
1287            public int getPagesCount(long userId, long nodeId, int status)
1288                    throws SystemException {
1289    
1290                    if (userId > 0) {
1291                            return wikiPagePersistence.countByU_N_S(userId, nodeId, status);
1292                    }
1293                    else {
1294                            return wikiPagePersistence.countByN_S(nodeId, status);
1295                    }
1296            }
1297    
1298            @Override
1299            public int getPagesCount(long nodeId, String title) throws SystemException {
1300                    return wikiPagePersistence.countByN_T(nodeId, title);
1301            }
1302    
1303            @Override
1304            public int getPagesCount(long nodeId, String title, boolean head)
1305                    throws SystemException {
1306    
1307                    return wikiPagePersistence.countByN_T_H(nodeId, title, head);
1308            }
1309    
1310            @Override
1311            public int getPagesCount(String format) throws SystemException {
1312                    return wikiPagePersistence.countByFormat(format);
1313            }
1314    
1315            /**
1316             * @deprecated As of 6.2.0, replaced by {@link #getRecentChanges(long, long,
1317             *             int, int)}
1318             */
1319            @Override
1320            public List<WikiPage> getRecentChanges(long nodeId, int start, int end)
1321                    throws PortalException, SystemException {
1322    
1323                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1324    
1325                    return getRecentChanges(node.getGroupId(), nodeId, start, end);
1326            }
1327    
1328            @Override
1329            public List<WikiPage> getRecentChanges(
1330                            long groupId, long nodeId, int start, int end)
1331                    throws SystemException {
1332    
1333                    Calendar cal = CalendarFactoryUtil.getCalendar();
1334    
1335                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1336    
1337                    return wikiPageFinder.findByCreateDate(
1338                            groupId, nodeId, cal.getTime(), false, start, end);
1339            }
1340    
1341            /**
1342             * @deprecated As of 6.2.0, replaced by {@link #getRecentChangesCount(long,
1343             *             long)}
1344             */
1345            @Override
1346            public int getRecentChangesCount(long nodeId)
1347                    throws PortalException, SystemException {
1348    
1349                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
1350    
1351                    return getRecentChangesCount(node.getGroupId(), nodeId);
1352            }
1353    
1354            @Override
1355            public int getRecentChangesCount(long groupId, long nodeId)
1356                    throws SystemException {
1357    
1358                    Calendar cal = CalendarFactoryUtil.getCalendar();
1359    
1360                    cal.add(Calendar.WEEK_OF_YEAR, -1);
1361    
1362                    return wikiPageFinder.countByCreateDate(
1363                            groupId, nodeId, cal.getTime(), false);
1364            }
1365    
1366            @Override
1367            public String[] getTempPageAttachmentNames(
1368                            long groupId, long userId, String tempFolderName)
1369                    throws PortalException, SystemException {
1370    
1371                    return TempFileUtil.getTempFileEntryNames(
1372                            groupId, userId, tempFolderName);
1373            }
1374    
1375            @Override
1376            public boolean hasDraftPage(long nodeId, String title)
1377                    throws SystemException {
1378    
1379                    int count = wikiPagePersistence.countByN_T_S(
1380                            nodeId, title, WorkflowConstants.STATUS_DRAFT);
1381    
1382                    if (count > 0) {
1383                            return true;
1384                    }
1385                    else {
1386                            return false;
1387                    }
1388            }
1389    
1390            @Override
1391            public void movePage(
1392                            long userId, long nodeId, String title, String newTitle,
1393                            boolean strict, ServiceContext serviceContext)
1394                    throws PortalException, SystemException {
1395    
1396                    validateTitle(newTitle);
1397    
1398                    // Check if the new title already exists
1399    
1400                    if (StringUtil.equalsIgnoreCase(title, newTitle)) {
1401                            throw new DuplicatePageException(newTitle);
1402                    }
1403    
1404                    if (isUsedTitle(nodeId, newTitle)) {
1405                            WikiPage page = getPage(nodeId, newTitle);
1406    
1407                            // Support moving back to a previously moved title
1408    
1409                            if (((page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
1410                                     (page.getContent().length() < 200)) ||
1411                                    !strict) {
1412    
1413                                    deletePage(nodeId, newTitle);
1414                            }
1415                            else {
1416                                    throw new DuplicatePageException(newTitle);
1417                            }
1418                    }
1419    
1420                    // All versions
1421    
1422                    List<WikiPage> versionPages = wikiPagePersistence.findByN_T(
1423                            nodeId, title);
1424    
1425                    if (versionPages.size() == 0) {
1426                            return;
1427                    }
1428    
1429                    for (WikiPage page : versionPages) {
1430                            page.setTitle(newTitle);
1431    
1432                            wikiPagePersistence.update(page);
1433                    }
1434    
1435                    // Children
1436    
1437                    List<WikiPage> children = wikiPagePersistence.findByN_P(nodeId, title);
1438    
1439                    for (WikiPage page : children) {
1440                            page.setParentTitle(newTitle);
1441    
1442                            wikiPagePersistence.update(page);
1443                    }
1444    
1445                    WikiPage page = versionPages.get(versionPages.size() - 1);
1446    
1447                    long resourcePrimKey = page.getResourcePrimKey();
1448    
1449                    // Page resource
1450    
1451                    WikiPageResource pageResource =
1452                            wikiPageResourcePersistence.findByPrimaryKey(resourcePrimKey);
1453    
1454                    pageResource.setTitle(newTitle);
1455    
1456                    wikiPageResourcePersistence.update(pageResource);
1457    
1458                    // Create stub page at the old location
1459    
1460                    double version = WikiPageConstants.VERSION_DEFAULT;
1461                    String summary = WikiPageConstants.MOVED + " to " + newTitle;
1462                    String format = page.getFormat();
1463                    boolean head = true;
1464                    String parentTitle = page.getParentTitle();
1465                    String redirectTitle = page.getTitle();
1466                    String content =
1467                            StringPool.DOUBLE_OPEN_BRACKET + redirectTitle +
1468                                    StringPool.DOUBLE_CLOSE_BRACKET;
1469    
1470                    serviceContext.setAddGroupPermissions(true);
1471                    serviceContext.setAddGuestPermissions(true);
1472    
1473                    populateServiceContext(serviceContext, page);
1474    
1475                    addPage(
1476                            userId, nodeId, title, version, content, summary, false, format,
1477                            head, parentTitle, redirectTitle, serviceContext);
1478    
1479                    // Move redirects to point to the page with the new title
1480    
1481                    List<WikiPage> redirectedPages = wikiPagePersistence.findByN_R(
1482                            nodeId, title);
1483    
1484                    for (WikiPage redirectedPage : redirectedPages) {
1485                            redirectedPage.setRedirectTitle(newTitle);
1486    
1487                            wikiPagePersistence.update(redirectedPage);
1488                    }
1489    
1490                    // Asset
1491    
1492                    updateAsset(
1493                            userId, page, serviceContext.getAssetCategoryIds(),
1494                            serviceContext.getAssetTagNames(),
1495                            serviceContext.getAssetLinkEntryIds());
1496    
1497                    // Indexer
1498    
1499                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1500                            WikiPage.class);
1501    
1502                    indexer.delete(
1503                            new Object[] {page.getCompanyId(), page.getNodeId(), title});
1504    
1505                    indexer.reindex(page);
1506            }
1507    
1508            @Override
1509            public void movePage(
1510                            long userId, long nodeId, String title, String newTitle,
1511                            ServiceContext serviceContext)
1512                    throws PortalException, SystemException {
1513    
1514                    movePage(userId, nodeId, title, newTitle, true, serviceContext);
1515            }
1516    
1517            @Override
1518            public FileEntry movePageAttachmentToTrash(
1519                            long userId, long nodeId, String title, String fileName)
1520                    throws PortalException, SystemException {
1521    
1522                    WikiPage page = getPage(nodeId, title);
1523    
1524                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1525                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1526    
1527                    fileEntry = PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1528                            userId, fileEntry.getFileEntryId());
1529    
1530                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1531    
1532                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1533                    extraDataJSONObject.put(
1534                            "fileEntryTitle", TrashUtil.getOriginalTitle(fileEntry.getTitle()));
1535                    extraDataJSONObject.put("title", page.getTitle());
1536                    extraDataJSONObject.put("version", page.getVersion());
1537    
1538                    socialActivityLocalService.addActivity(
1539                            userId, page.getGroupId(), WikiPage.class.getName(),
1540                            page.getResourcePrimKey(),
1541                            SocialActivityConstants.TYPE_MOVE_ATTACHMENT_TO_TRASH,
1542                            extraDataJSONObject.toString(), 0);
1543    
1544                    return fileEntry;
1545            }
1546    
1547            @Override
1548            public WikiPage movePageToTrash(long userId, long nodeId, String title)
1549                    throws PortalException, SystemException {
1550    
1551                    List<WikiPage> wikiPages = wikiPagePersistence.findByN_T_H(
1552                            nodeId, title, true, 0, 1);
1553    
1554                    if (!wikiPages.isEmpty()) {
1555                            return movePageToTrash(userId, wikiPages.get(0));
1556                    }
1557    
1558                    return null;
1559            }
1560    
1561            @Override
1562            public WikiPage movePageToTrash(
1563                            long userId, long nodeId, String title, double version)
1564                    throws PortalException, SystemException {
1565    
1566                    WikiPage page = wikiPagePersistence.findByN_T_V(nodeId, title, version);
1567    
1568                    return movePageToTrash(userId, page);
1569            }
1570    
1571            @Override
1572            public WikiPage movePageToTrash(long userId, WikiPage page)
1573                    throws PortalException, SystemException {
1574    
1575                    // Page
1576    
1577                    int oldStatus = page.getStatus();
1578                    String oldTitle = page.getTitle();
1579    
1580                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1581                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
1582    
1583                            wikiPagePersistence.update(page);
1584                    }
1585    
1586                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
1587                            page.getResourcePrimKey(), page.getNodeId(), false);
1588    
1589                    pageVersions = ListUtil.sort(pageVersions, new PageVersionComparator());
1590    
1591                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
1592                            new ArrayList<ObjectValuePair<Long, Integer>>();
1593    
1594                    if ((pageVersions != null) && !pageVersions.isEmpty()) {
1595                            pageVersionStatusOVPs = getPageVersionStatuses(pageVersions);
1596                    }
1597    
1598                    page = updateStatus(
1599                            userId, page, WorkflowConstants.STATUS_IN_TRASH,
1600                            new ServiceContext());
1601    
1602                    // Trash
1603    
1604                    WikiPageResource pageResource =
1605                            wikiPageResourcePersistence.fetchByPrimaryKey(
1606                                    page.getResourcePrimKey());
1607    
1608                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
1609    
1610                    typeSettingsProperties.put("title", page.getTitle());
1611    
1612                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
1613                            userId, page.getGroupId(), WikiPage.class.getName(),
1614                            page.getResourcePrimKey(), pageResource.getUuid(), null, oldStatus,
1615                            pageVersionStatusOVPs, typeSettingsProperties);
1616    
1617                    String trashTitle = TrashUtil.getTrashTitle(trashEntry.getEntryId());
1618    
1619                    for (WikiPage pageVersion : pageVersions) {
1620                            pageVersion.setTitle(trashTitle);
1621                            pageVersion.setStatus(WorkflowConstants.STATUS_IN_TRASH);
1622    
1623                            wikiPagePersistence.update(pageVersion);
1624                    }
1625    
1626                    pageResource.setTitle(trashTitle);
1627    
1628                    wikiPageResourcePersistence.update(pageResource);
1629    
1630                    page.setTitle(trashTitle);
1631    
1632                    wikiPagePersistence.update(page);
1633    
1634                    // Children
1635    
1636                    List<WikiPage> children = wikiPagePersistence.findByN_H_P(
1637                            page.getNodeId(), true, oldTitle);
1638    
1639                    for (WikiPage curPage : children) {
1640                            curPage.setParentTitle(trashTitle);
1641    
1642                            wikiPagePersistence.update(curPage);
1643    
1644                            if (!curPage.isInTrash()) {
1645                                    movePageToTrash(userId, curPage);
1646                            }
1647                    }
1648    
1649                    // Redirect Pages
1650    
1651                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_H_R(
1652                            page.getNodeId(), true, oldTitle);
1653    
1654                    for (WikiPage curPage : redirectPages) {
1655                            curPage.setRedirectTitle(trashTitle);
1656    
1657                            wikiPagePersistence.update(curPage);
1658    
1659                            if (!curPage.isInTrash()) {
1660                                    movePageToTrash(userId, curPage);
1661                            }
1662                    }
1663    
1664                    // Asset
1665    
1666                    assetEntryLocalService.updateVisible(
1667                            WikiPage.class.getName(), page.getResourcePrimKey(), false);
1668    
1669                    // Attachments
1670    
1671                    for (FileEntry fileEntry : page.getAttachmentsFileEntries()) {
1672                            PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1673                                    userId, fileEntry.getFileEntryId());
1674                    }
1675    
1676                    // Comment
1677    
1678                    mbMessageLocalService.moveDiscussionToTrash(
1679                            WikiPage.class.getName(), page.getResourcePrimKey());
1680    
1681                    // Social
1682    
1683                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1684    
1685                    extraDataJSONObject.put(
1686                            "title", TrashUtil.getOriginalTitle(page.getTitle()));
1687                    extraDataJSONObject.put("version", page.getVersion());
1688    
1689                    socialActivityLocalService.addActivity(
1690                            userId, page.getGroupId(), WikiPage.class.getName(),
1691                            page.getResourcePrimKey(),
1692                            SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1693                            extraDataJSONObject.toString(), 0);
1694    
1695                    if (!pageVersions.isEmpty()) {
1696                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1697                                    WikiPage.class);
1698    
1699                            for (WikiPage pageVersion : pageVersions) {
1700                                    indexer.reindex(pageVersion);
1701                            }
1702                    }
1703    
1704                    // Workflow
1705    
1706                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1707                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1708                                    page.getCompanyId(), page.getGroupId(),
1709                                    WikiPage.class.getName(), page.getPageId());
1710                    }
1711    
1712                    return page;
1713            }
1714    
1715            @Override
1716            public void restorePageAttachmentFromTrash(
1717                            long userId, long nodeId, String title, String fileName)
1718                    throws PortalException, SystemException {
1719    
1720                    WikiPage page = getPage(nodeId, title);
1721    
1722                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1723                            page.getGroupId(), page.getAttachmentsFolderId(), fileName);
1724    
1725                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1726    
1727                    extraDataJSONObject.put("fileEntryId", fileEntry.getFileEntryId());
1728                    extraDataJSONObject.put("fileEntryTitle", TrashUtil.getOriginalTitle(
1729                            fileEntry.getTitle()));
1730                    extraDataJSONObject.put("title", page.getTitle());
1731                    extraDataJSONObject.put("version", page.getVersion());
1732    
1733                    PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1734                            userId, fileEntry.getFileEntryId());
1735    
1736                    socialActivityLocalService.addActivity(
1737                            userId, page.getGroupId(), WikiPage.class.getName(),
1738                            page.getResourcePrimKey(),
1739                            SocialActivityConstants.TYPE_RESTORE_ATTACHMENT_FROM_TRASH,
1740                            extraDataJSONObject.toString(), 0);
1741            }
1742    
1743            @Override
1744            public void restorePageFromTrash(long userId, WikiPage page)
1745                    throws PortalException, SystemException {
1746    
1747                    String title = page.getTitle();
1748    
1749                    String originalTitle = TrashUtil.getOriginalTitle(title);
1750    
1751                    List<WikiPage> pageVersions = wikiPagePersistence.findByR_N_H(
1752                            page.getResourcePrimKey(), page.getNodeId(), false);
1753    
1754                    for (WikiPage pageVersion : pageVersions) {
1755                            pageVersion.setTitle(originalTitle);
1756    
1757                            wikiPagePersistence.update(pageVersion);
1758                    }
1759    
1760                    WikiPageResource pageResource =
1761                            wikiPageResourcePersistence.fetchByPrimaryKey(
1762                                    page.getResourcePrimKey());
1763    
1764                    pageResource.setTitle(originalTitle);
1765    
1766                    wikiPageResourcePersistence.update(pageResource);
1767    
1768                    page.setTitle(originalTitle);
1769    
1770                    WikiPage parentPage = page.getParentPage();
1771    
1772                    if ((parentPage != null) && parentPage.isInTrash()) {
1773                            page.setParentTitle(StringPool.BLANK);
1774                    }
1775    
1776                    WikiPage redirectPage = page.getRedirectPage();
1777    
1778                    if ((redirectPage != null) && redirectPage.isInTrash()) {
1779                            page.setRedirectTitle(StringPool.BLANK);
1780                    }
1781    
1782                    wikiPagePersistence.update(page);
1783    
1784                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1785                            WikiPage.class.getName(), page.getResourcePrimKey());
1786    
1787                    updateStatus(
1788                            userId, page, trashEntry.getStatus(), new ServiceContext());
1789    
1790                    // Children
1791    
1792                    List<WikiPage> children = wikiPagePersistence.findByN_H_P_S(
1793                            page.getNodeId(), true, title, WorkflowConstants.STATUS_IN_TRASH);
1794    
1795                    for (WikiPage curPage : children) {
1796                            curPage.setParentTitle(originalTitle);
1797    
1798                            wikiPagePersistence.update(curPage);
1799    
1800                            if (curPage.isInTrash()) {
1801                                    restorePageFromTrash(userId, curPage);
1802                            }
1803                    }
1804    
1805                    // Redirect Pages
1806    
1807                    List<WikiPage> redirectPages = wikiPagePersistence.findByN_H_R(
1808                            page.getNodeId(), true, title);
1809    
1810                    for (WikiPage curPage : redirectPages) {
1811                            curPage.setRedirectTitle(originalTitle);
1812    
1813                            wikiPagePersistence.update(curPage);
1814    
1815                            if (curPage.isInTrash()) {
1816                                    restorePageFromTrash(userId, curPage);
1817                            }
1818                    }
1819    
1820                    // Attachments
1821    
1822                    for (FileEntry fileEntry : page.getAttachmentsFileEntries()) {
1823                            PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1824                                    userId, fileEntry.getFileEntryId());
1825                    }
1826    
1827                    // Comment
1828    
1829                    mbMessageLocalService.restoreDiscussionFromTrash(
1830                            WikiPage.class.getName(), page.getResourcePrimKey());
1831    
1832                    // Trash
1833    
1834                    List<TrashVersion> trashVersions = trashVersionLocalService.getVersions(
1835                            trashEntry.getEntryId());
1836    
1837                    for (TrashVersion trashVersion : trashVersions) {
1838                            WikiPage trashArticleVersion = wikiPagePersistence.findByPrimaryKey(
1839                                    trashVersion.getClassPK());
1840    
1841                            trashArticleVersion.setStatus(trashVersion.getStatus());
1842    
1843                            wikiPagePersistence.update(trashArticleVersion);
1844                    }
1845    
1846                    trashEntryLocalService.deleteEntry(
1847                            WikiPage.class.getName(), page.getResourcePrimKey());
1848    
1849                    // Social
1850    
1851                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1852    
1853                    extraDataJSONObject.put("title", page.getTitle());
1854                    extraDataJSONObject.put("version", page.getVersion());
1855    
1856                    socialActivityLocalService.addActivity(
1857                            userId, page.getGroupId(), WikiPage.class.getName(),
1858                            page.getResourcePrimKey(),
1859                            SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1860                            extraDataJSONObject.toString(), 0);
1861    
1862                    if (!pageVersions.isEmpty()) {
1863                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1864                                    WikiPage.class);
1865    
1866                            for (WikiPage pageVersion : pageVersions) {
1867                                    indexer.reindex(pageVersion);
1868                            }
1869                    }
1870            }
1871    
1872            @Override
1873            public WikiPage revertPage(
1874                            long userId, long nodeId, String title, double version,
1875                            ServiceContext serviceContext)
1876                    throws PortalException, SystemException {
1877    
1878                    WikiPage oldPage = getPage(nodeId, title, version);
1879    
1880                    populateServiceContext(serviceContext, oldPage);
1881    
1882                    return updatePage(
1883                            userId, nodeId, title, 0, oldPage.getContent(),
1884                            WikiPageConstants.REVERTED + " to " + version, false,
1885                            oldPage.getFormat(), getParentPageTitle(oldPage),
1886                            oldPage.getRedirectTitle(), serviceContext);
1887            }
1888    
1889            @Override
1890            public void subscribePage(long userId, long nodeId, String title)
1891                    throws PortalException, SystemException {
1892    
1893                    WikiPage page = getPage(nodeId, title);
1894    
1895                    subscriptionLocalService.addSubscription(
1896                            userId, page.getGroupId(), WikiPage.class.getName(),
1897                            page.getResourcePrimKey());
1898            }
1899    
1900            @Override
1901            public void unsubscribePage(long userId, long nodeId, String title)
1902                    throws PortalException, SystemException {
1903    
1904                    WikiPage page = getPage(nodeId, title);
1905    
1906                    subscriptionLocalService.deleteSubscription(
1907                            userId, WikiPage.class.getName(), page.getResourcePrimKey());
1908            }
1909    
1910            @Override
1911            public void updateAsset(
1912                            long userId, WikiPage page, long[] assetCategoryIds,
1913                            String[] assetTagNames, long[] assetLinkEntryIds)
1914                    throws PortalException, SystemException {
1915    
1916                    boolean addDraftAssetEntry = false;
1917    
1918                    if (!page.isApproved() &&
1919                            (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
1920    
1921                            int approvedPagesCount = wikiPagePersistence.countByN_T_S(
1922                                    page.getNodeId(), page.getTitle(),
1923                                    WorkflowConstants.STATUS_APPROVED);
1924    
1925                            if (approvedPagesCount > 0) {
1926                                    addDraftAssetEntry = true;
1927                            }
1928                    }
1929    
1930                    AssetEntry assetEntry = null;
1931    
1932                    if (addDraftAssetEntry) {
1933                            assetEntry = assetEntryLocalService.updateEntry(
1934                                    userId, page.getGroupId(), page.getCreateDate(),
1935                                    page.getModifiedDate(), WikiPage.class.getName(),
1936                                    page.getPrimaryKey(), page.getUuid(), 0, assetCategoryIds,
1937                                    assetTagNames, false, null, null, null, ContentTypes.TEXT_HTML,
1938                                    page.getTitle(), null, null, null, null, 0, 0, null, false);
1939                    }
1940                    else {
1941                            assetEntry = assetEntryLocalService.updateEntry(
1942                                    userId, page.getGroupId(), page.getCreateDate(),
1943                                    page.getModifiedDate(), WikiPage.class.getName(),
1944                                    page.getResourcePrimKey(), page.getUuid(), 0, assetCategoryIds,
1945                                    assetTagNames, page.isApproved(), null, null, null,
1946                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null, null, null,
1947                                    0, 0, null, false);
1948                    }
1949    
1950                    assetLinkLocalService.updateLinks(
1951                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1952                            AssetLinkConstants.TYPE_RELATED);
1953            }
1954    
1955            @Override
1956            public WikiPage updatePage(
1957                            long userId, long nodeId, String title, double version,
1958                            String content, String summary, boolean minorEdit, String format,
1959                            String parentTitle, String redirectTitle,
1960                            ServiceContext serviceContext)
1961                    throws PortalException, SystemException {
1962    
1963                    // Page
1964    
1965                    User user = userPersistence.findByPrimaryKey(userId);
1966                    Date now = new Date();
1967    
1968                    WikiPage oldPage = null;
1969    
1970                    try {
1971                            oldPage = wikiPagePersistence.findByN_T_First(nodeId, title, null);
1972                    }
1973                    catch (NoSuchPageException nspe) {
1974                            return addPage(
1975                                    userId, nodeId, title, WikiPageConstants.VERSION_DEFAULT,
1976                                    content, summary, minorEdit, format, true, parentTitle,
1977                                    redirectTitle, serviceContext);
1978                    }
1979    
1980                    long pageId = 0;
1981    
1982                    if (oldPage.isApproved()) {
1983                            pageId = counterLocalService.increment();
1984                    }
1985                    else {
1986                            pageId = oldPage.getPageId();
1987                    }
1988    
1989                    content = SanitizerUtil.sanitize(
1990                            user.getCompanyId(), oldPage.getGroupId(), userId,
1991                            WikiPage.class.getName(), pageId, "text/" + format, content);
1992    
1993                    validate(nodeId, content, format);
1994    
1995                    double oldVersion = oldPage.getVersion();
1996    
1997                    if ((version > 0) && (version != oldVersion)) {
1998                            throw new PageVersionException();
1999                    }
2000    
2001                    serviceContext.validateModifiedDate(
2002                            oldPage, PageVersionException.class);
2003    
2004                    long resourcePrimKey =
2005                            wikiPageResourceLocalService.getPageResourcePrimKey(nodeId, title);
2006                    long groupId = oldPage.getGroupId();
2007    
2008                    WikiPage page = oldPage;
2009    
2010                    double newVersion = oldVersion;
2011    
2012                    if (oldPage.isApproved()) {
2013                            newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
2014    
2015                            page = wikiPagePersistence.create(pageId);
2016    
2017                            page.setUuid(serviceContext.getUuid());
2018                    }
2019    
2020                    page.setResourcePrimKey(resourcePrimKey);
2021                    page.setGroupId(groupId);
2022                    page.setCompanyId(user.getCompanyId());
2023                    page.setUserId(user.getUserId());
2024                    page.setUserName(user.getFullName());
2025                    page.setCreateDate(serviceContext.getModifiedDate(now));
2026                    page.setModifiedDate(serviceContext.getModifiedDate(now));
2027                    page.setNodeId(nodeId);
2028                    page.setTitle(title);
2029                    page.setVersion(newVersion);
2030                    page.setMinorEdit(minorEdit);
2031                    page.setContent(content);
2032    
2033                    if (oldPage.isPending()) {
2034                            page.setStatus(oldPage.getStatus());
2035                    }
2036                    else {
2037                            page.setStatus(WorkflowConstants.STATUS_DRAFT);
2038                    }
2039    
2040                    page.setSummary(summary);
2041                    page.setFormat(format);
2042    
2043                    if (Validator.isNotNull(parentTitle)) {
2044                            page.setParentTitle(parentTitle);
2045                    }
2046    
2047                    if (Validator.isNotNull(redirectTitle)) {
2048                            page.setRedirectTitle(redirectTitle);
2049                    }
2050    
2051                    page.setExpandoBridgeAttributes(serviceContext);
2052    
2053                    wikiPagePersistence.update(page);
2054    
2055                    // Node
2056    
2057                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
2058    
2059                    node.setLastPostDate(serviceContext.getModifiedDate(now));
2060    
2061                    wikiNodePersistence.update(node);
2062    
2063                    // Asset
2064    
2065                    updateAsset(
2066                            userId, page, serviceContext.getAssetCategoryIds(),
2067                            serviceContext.getAssetTagNames(),
2068                            serviceContext.getAssetLinkEntryIds());
2069    
2070                    // Social
2071    
2072                    if (!page.isMinorEdit() ||
2073                            PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY) {
2074    
2075                            if (oldVersion == newVersion) {
2076                                    SocialActivity lastSocialActivity =
2077                                            socialActivityLocalService.fetchFirstActivity(
2078                                                    WikiPage.class.getName(), page.getResourcePrimKey(),
2079                                                    WikiActivityKeys.UPDATE_PAGE);
2080    
2081                                    if (lastSocialActivity != null) {
2082                                            lastSocialActivity.setCreateDate(now.getTime() + 1);
2083                                            lastSocialActivity.setUserId(serviceContext.getUserId());
2084    
2085                                            socialActivityPersistence.update(lastSocialActivity);
2086                                    }
2087                            }
2088                            else {
2089                                    JSONObject extraDataJSONObject =
2090                                            JSONFactoryUtil.createJSONObject();
2091    
2092                                    extraDataJSONObject.put("title", page.getTitle());
2093                                    extraDataJSONObject.put("version", page.getVersion());
2094    
2095                                    socialActivityLocalService.addActivity(
2096                                            userId, page.getGroupId(), WikiPage.class.getName(),
2097                                            page.getResourcePrimKey(), WikiActivityKeys.UPDATE_PAGE,
2098                                            extraDataJSONObject.toString(), 0);
2099                            }
2100                    }
2101    
2102                    // Workflow
2103    
2104                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
2105                            user.getCompanyId(), page.getGroupId(), userId,
2106                            WikiPage.class.getName(), page.getPageId(), page, serviceContext);
2107    
2108                    return page;
2109            }
2110    
2111            @Override
2112            public WikiPage updateStatus(
2113                            long userId, long resourcePrimKey, int status,
2114                            ServiceContext serviceContext)
2115                    throws PortalException, SystemException {
2116    
2117                    WikiPageResource pageResource =
2118                            wikiPageResourceLocalService.getPageResource(resourcePrimKey);
2119    
2120                    List<WikiPage> pages = wikiPagePersistence.findByN_T(
2121                            pageResource.getNodeId(), pageResource.getTitle(), 0, 1,
2122                            new PageVersionComparator());
2123    
2124                    WikiPage page = null;
2125    
2126                    if (!pages.isEmpty()) {
2127                            page = pages.get(0);
2128                    }
2129                    else {
2130                            throw new NoSuchPageException(
2131                                    "{resourcePrimKey=" + resourcePrimKey + "}");
2132                    }
2133    
2134                    return updateStatus(userId, page, status, serviceContext);
2135            }
2136    
2137            @Override
2138            public WikiPage updateStatus(
2139                            long userId, WikiPage page, int status,
2140                            ServiceContext serviceContext)
2141                    throws PortalException, SystemException {
2142    
2143                    // Page
2144    
2145                    User user = userPersistence.findByPrimaryKey(userId);
2146                    WikiNode node = wikiNodePersistence.findByPrimaryKey(page.getNodeId());
2147    
2148                    Date now = new Date();
2149    
2150                    int oldStatus = page.getStatus();
2151    
2152                    page.setStatus(status);
2153                    page.setStatusByUserId(userId);
2154                    page.setStatusByUserName(user.getFullName());
2155                    page.setStatusDate(now);
2156    
2157                    wikiPagePersistence.update(page);
2158    
2159                    if (status == WorkflowConstants.STATUS_APPROVED) {
2160    
2161                            // Asset
2162    
2163                            if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2164                                    (page.getVersion() != WikiPageConstants.VERSION_DEFAULT)) {
2165    
2166                                    AssetEntry draftAssetEntry = assetEntryLocalService.fetchEntry(
2167                                            WikiPage.class.getName(), page.getPrimaryKey());
2168    
2169                                    if (draftAssetEntry != null) {
2170                                            long[] assetCategoryIds = draftAssetEntry.getCategoryIds();
2171                                            String[] assetTagNames = draftAssetEntry.getTagNames();
2172    
2173                                            List<AssetLink> assetLinks =
2174                                                    assetLinkLocalService.getDirectLinks(
2175                                                            draftAssetEntry.getEntryId(),
2176                                                            AssetLinkConstants.TYPE_RELATED);
2177    
2178                                            long[] assetLinkEntryIds = StringUtil.split(
2179                                                    ListUtil.toString(
2180                                                            assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2181    
2182                                            AssetEntry assetEntry = assetEntryLocalService.updateEntry(
2183                                                    userId, page.getGroupId(), page.getCreateDate(),
2184                                                    page.getModifiedDate(), WikiPage.class.getName(),
2185                                                    page.getResourcePrimKey(), page.getUuid(), 0,
2186                                                    assetCategoryIds, assetTagNames, true, null, null, null,
2187                                                    ContentTypes.TEXT_HTML, page.getTitle(), null, null,
2188                                                    null, null, 0, 0, null, false);
2189    
2190                                            // Asset Links
2191    
2192                                            assetLinkLocalService.updateLinks(
2193                                                    userId, assetEntry.getEntryId(), assetLinkEntryIds,
2194                                                    AssetLinkConstants.TYPE_RELATED);
2195    
2196                                            SystemEventHierarchyEntryThreadLocal.push(WikiPage.class);
2197    
2198                                            try {
2199                                                    assetEntryLocalService.deleteEntry(
2200                                                            draftAssetEntry.getEntryId());
2201                                            }
2202                                            finally {
2203                                                    SystemEventHierarchyEntryThreadLocal.pop(
2204                                                            WikiPage.class);
2205                                            }
2206                                    }
2207                            }
2208    
2209                            assetEntryLocalService.updateVisible(
2210                                    WikiPage.class.getName(), page.getResourcePrimKey(), true);
2211    
2212                            // Social
2213    
2214                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
2215                                    (page.getVersion() == WikiPageConstants.VERSION_DEFAULT) &&
2216                                    (!page.isMinorEdit() ||
2217                                     PropsValues.WIKI_PAGE_MINOR_EDIT_ADD_SOCIAL_ACTIVITY)) {
2218    
2219                                    JSONObject extraDataJSONObject =
2220                                            JSONFactoryUtil.createJSONObject();
2221    
2222                                    extraDataJSONObject.put("title", page.getTitle());
2223                                    extraDataJSONObject.put("version", page.getVersion());
2224    
2225                                    socialActivityLocalService.addActivity(
2226                                            userId, page.getGroupId(), WikiPage.class.getName(),
2227                                            page.getResourcePrimKey(), WikiActivityKeys.ADD_PAGE,
2228                                            extraDataJSONObject.toString(), 0);
2229                            }
2230    
2231                            // Subscriptions
2232    
2233                            if (NotificationThreadLocal.isEnabled() &&
2234                                    (!page.isMinorEdit() ||
2235                                     PropsValues.WIKI_PAGE_MINOR_EDIT_SEND_EMAIL)) {
2236    
2237                                    boolean update = false;
2238    
2239                                    if (page.getVersion() > WikiPageConstants.VERSION_DEFAULT) {
2240                                            update = true;
2241                                    }
2242    
2243                                    notifySubscribers(node, page, serviceContext, update);
2244                            }
2245    
2246                            // Cache
2247    
2248                            clearPageCache(page);
2249                    }
2250    
2251                    // Head
2252    
2253                    if (status == WorkflowConstants.STATUS_APPROVED) {
2254                            page.setHead(true);
2255    
2256                            List<WikiPage> pages = wikiPagePersistence.findByN_T_H(
2257                                    page.getNodeId(), page.getTitle(), true);
2258    
2259                            for (WikiPage curPage : pages) {
2260                                    if (!curPage.equals(page)) {
2261                                            curPage.setHead(false);
2262    
2263                                            wikiPagePersistence.update(curPage);
2264                                    }
2265                            }
2266                    }
2267                    else if (status != WorkflowConstants.STATUS_IN_TRASH) {
2268                            page.setHead(false);
2269    
2270                            List<WikiPage> pages = wikiPagePersistence.findByN_T_S(
2271                                    page.getNodeId(), page.getTitle(),
2272                                    WorkflowConstants.STATUS_APPROVED);
2273    
2274                            for (WikiPage curPage : pages) {
2275                                    if (!curPage.equals(page)) {
2276                                            curPage.setHead(true);
2277    
2278                                            wikiPagePersistence.update(curPage);
2279    
2280                                            break;
2281                                    }
2282                            }
2283                    }
2284    
2285                    // Indexer
2286    
2287                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2288                            WikiPage.class);
2289    
2290                    indexer.reindex(page);
2291    
2292                    return wikiPagePersistence.update(page);
2293            }
2294    
2295            @Override
2296            public void validateTitle(String title) throws PortalException {
2297                    if (title.equals("all_pages") || title.equals("orphan_pages") ||
2298                            title.equals("recent_changes")) {
2299    
2300                            throw new PageTitleException(title + " is reserved");
2301                    }
2302    
2303                    if (Validator.isNotNull(PropsValues.WIKI_PAGE_TITLES_REGEXP)) {
2304                            Pattern pattern = Pattern.compile(
2305                                    PropsValues.WIKI_PAGE_TITLES_REGEXP);
2306    
2307                            Matcher matcher = pattern.matcher(title);
2308    
2309                            if (!matcher.matches()) {
2310                                    throw new PageTitleException();
2311                            }
2312                    }
2313            }
2314    
2315            protected void clearPageCache(WikiPage page) {
2316                    if (!WikiCacheThreadLocal.isClearCache()) {
2317                            return;
2318                    }
2319    
2320                    WikiCacheUtil.clearCache(page.getNodeId());
2321            }
2322    
2323            protected void deletePageAttachment(long fileEntryId)
2324                    throws PortalException, SystemException {
2325    
2326                    PortletFileRepositoryUtil.deletePortletFileEntry(fileEntryId);
2327            }
2328    
2329            protected String getDiffsURL(
2330                            WikiNode node, WikiPage page, WikiPage previousVersionPage,
2331                            ServiceContext serviceContext)
2332                    throws PortalException, SystemException {
2333    
2334                    if (previousVersionPage == null) {
2335                            return StringPool.BLANK;
2336                    }
2337    
2338                    HttpServletRequest request = serviceContext.getRequest();
2339    
2340                    if (request == null) {
2341                            return StringPool.BLANK;
2342                    }
2343    
2344                    String portletId = null;
2345                    long plid = LayoutConstants.DEFAULT_PLID;
2346                    String strutsAction = null;
2347    
2348                    if (serviceContext.getPlid() != LayoutConstants.DEFAULT_PLID) {
2349                            portletId = PortletKeys.WIKI;
2350                            plid = serviceContext.getPlid();
2351                            strutsAction = "/wiki/compare_versions";
2352                    }
2353                    else {
2354                            portletId = PortletKeys.WIKI_ADMIN;
2355                            plid = PortalUtil.getControlPanelPlid(
2356                                    serviceContext.getCompanyId());
2357                            strutsAction = "/wiki_admin/compare_versions";
2358                    }
2359    
2360                    PortletURL portletURL = PortletURLFactoryUtil.create(
2361                            request, portletId, plid, PortletRequest.RENDER_PHASE);
2362    
2363                    portletURL.setParameter("struts_action", strutsAction);
2364                    portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2365                    portletURL.setParameter("title", page.getTitle());
2366                    portletURL.setParameter(
2367                            "sourceVersion", String.valueOf(previousVersionPage.getVersion()));
2368                    portletURL.setParameter(
2369                            "targetVersion", String.valueOf(page.getVersion()));
2370                    portletURL.setParameter("type", "html");
2371    
2372                    return portletURL.toString();
2373            }
2374    
2375            protected String getPageURL(
2376                            WikiNode node, WikiPage page, ServiceContext serviceContext)
2377                    throws PortalException, SystemException {
2378    
2379                    HttpServletRequest request = serviceContext.getRequest();
2380    
2381                    if (request == null) {
2382                            return StringPool.BLANK;
2383                    }
2384    
2385                    String layoutFullURL = getLayoutURL(
2386                            node.getGroupId(), PortletKeys.WIKI, serviceContext);
2387    
2388                    if (Validator.isNotNull(layoutFullURL)) {
2389                            return layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "wiki/" +
2390                                    node.getNodeId() + StringPool.SLASH +
2391                                            HttpUtil.encodeURL(WikiUtil.escapeName(page.getTitle()));
2392                    }
2393                    else {
2394                            long controlPanelPlid = PortalUtil.getControlPanelPlid(
2395                                    serviceContext.getCompanyId());
2396    
2397                            PortletURL portletURL = PortletURLFactoryUtil.create(
2398                                    request, PortletKeys.WIKI_ADMIN, controlPanelPlid,
2399                                    PortletRequest.RENDER_PHASE);
2400    
2401                            portletURL.setParameter(
2402                                    "struts_action", "/wiki_admin/view_page_activities");
2403                            portletURL.setParameter("nodeId", String.valueOf(node.getNodeId()));
2404                            portletURL.setParameter("title", page.getTitle());
2405    
2406                            return portletURL.toString();
2407                    }
2408            }
2409    
2410            protected List<ObjectValuePair<Long, Integer>> getPageVersionStatuses(
2411                    List<WikiPage> pages) {
2412    
2413                    List<ObjectValuePair<Long, Integer>> pageVersionStatusOVPs =
2414                            new ArrayList<ObjectValuePair<Long, Integer>>(pages.size());
2415    
2416                    for (WikiPage page : pages) {
2417                            int status = page.getStatus();
2418    
2419                            if (status == WorkflowConstants.STATUS_PENDING) {
2420                                    status = WorkflowConstants.STATUS_DRAFT;
2421                            }
2422    
2423                            ObjectValuePair<Long, Integer> pageVersionStatusOVP =
2424                                    new ObjectValuePair<Long, Integer>(page.getPageId(), status);
2425    
2426                            pageVersionStatusOVPs.add(pageVersionStatusOVP);
2427                    }
2428    
2429                    return pageVersionStatusOVPs;
2430            }
2431    
2432            protected String getParentPageTitle(WikiPage page) {
2433    
2434                    // LPS-4586
2435    
2436                    try {
2437                            WikiPage parentPage = getPage(
2438                                    page.getNodeId(), page.getParentTitle());
2439    
2440                            return parentPage.getTitle();
2441                    }
2442                    catch (Exception e) {
2443                            return null;
2444                    }
2445            }
2446    
2447            protected WikiPage getPreviousVersionPage(WikiPage page)
2448                    throws PortalException, SystemException {
2449    
2450                    double previousVersion = MathUtil.format(page.getVersion() - 0.1, 1, 1);
2451    
2452                    if (previousVersion < 1) {
2453                            return null;
2454                    }
2455    
2456                    return getPage(page.getNodeId(), page.getTitle(), previousVersion);
2457            }
2458    
2459            protected boolean isLinkedTo(WikiPage page, String targetTitle)
2460                    throws PortalException {
2461    
2462                    Map<String, Boolean> links = WikiCacheUtil.getOutgoingLinks(page);
2463    
2464                    Boolean link = links.get(StringUtil.toLowerCase(targetTitle));
2465    
2466                    if (link != null) {
2467                            return true;
2468                    }
2469                    else {
2470                            return false;
2471                    }
2472            }
2473    
2474            protected boolean isUsedTitle(long nodeId, String title)
2475                    throws SystemException {
2476    
2477                    if (getPagesCount(nodeId, title, true) > 0) {
2478                            return true;
2479                    }
2480                    else {
2481                            return false;
2482                    }
2483            }
2484    
2485            protected void notifySubscribers(
2486                            WikiNode node, WikiPage page, ServiceContext serviceContext,
2487                            boolean update)
2488                    throws PortalException, SystemException {
2489    
2490                    String layoutFullURL = serviceContext.getLayoutFullURL();
2491    
2492                    if (!page.isApproved() || Validator.isNull(layoutFullURL)) {
2493                            return;
2494                    }
2495    
2496                    PortletPreferences preferences = null;
2497    
2498                    String rootPortletId = serviceContext.getRootPortletId();
2499    
2500                    if (Validator.isNull(rootPortletId) ||
2501                            !rootPortletId.equals(PortletKeys.WIKI_DISPLAY)) {
2502    
2503                            preferences = ServiceContextUtil.getPortletPreferences(
2504                                    serviceContext);
2505                    }
2506    
2507                    if (preferences == null) {
2508                            preferences = portletPreferencesLocalService.getPreferences(
2509                                    node.getCompanyId(), node.getGroupId(),
2510                                    PortletKeys.PREFS_OWNER_TYPE_GROUP,
2511                                    PortletKeys.PREFS_PLID_SHARED, PortletKeys.WIKI_ADMIN, null);
2512                    }
2513    
2514                    if (!update && WikiUtil.getEmailPageAddedEnabled(preferences)) {
2515                    }
2516                    else if (update && WikiUtil.getEmailPageUpdatedEnabled(preferences)) {
2517                    }
2518                    else {
2519                            return;
2520                    }
2521    
2522                    String portalURL = serviceContext.getPortalURL();
2523    
2524                    WikiPage previousVersionPage = getPreviousVersionPage(page);
2525    
2526                    String attachmentURLPrefix = WikiUtil.getAttachmentURLPrefix(
2527                            serviceContext.getPathMain(), serviceContext.getPlid(),
2528                            page.getNodeId(), page.getTitle());
2529    
2530                    attachmentURLPrefix = portalURL + attachmentURLPrefix;
2531    
2532                    String pageDiffs = StringPool.BLANK;
2533    
2534                    try {
2535                            pageDiffs = WikiUtil.diffHtml(
2536                                    previousVersionPage, page, null, null, attachmentURLPrefix);
2537                    }
2538                    catch (Exception e) {
2539                    }
2540    
2541                    String pageContent = null;
2542    
2543                    if (Validator.equals(page.getFormat(), "creole")) {
2544                            pageContent = WikiUtil.convert(
2545                                    page, null, null, attachmentURLPrefix);
2546                    }
2547                    else {
2548                            pageContent = page.getContent();
2549                            pageContent = WikiUtil.processContent(pageContent);
2550                    }
2551    
2552                    String fromName = WikiUtil.getEmailFromName(
2553                            preferences, page.getCompanyId());
2554                    String fromAddress = WikiUtil.getEmailFromAddress(
2555                            preferences, page.getCompanyId());
2556    
2557                    String subject = null;
2558                    String body = null;
2559                    String signature = null;
2560    
2561                    if (update) {
2562                            subject = WikiUtil.getEmailPageUpdatedSubject(preferences);
2563                            body = WikiUtil.getEmailPageUpdatedBody(preferences);
2564                            signature = WikiUtil.getEmailPageUpdatedSignature(preferences);
2565                    }
2566                    else {
2567                            subject = WikiUtil.getEmailPageAddedSubject(preferences);
2568                            body = WikiUtil.getEmailPageAddedBody(preferences);
2569                            signature = WikiUtil.getEmailPageAddedSignature(preferences);
2570                    }
2571    
2572                    if (Validator.isNotNull(signature)) {
2573                            body += "\n" + signature;
2574                    }
2575    
2576                    SubscriptionSender subscriptionSender = new SubscriptionSender();
2577    
2578                    subscriptionSender.setBody(body);
2579                    subscriptionSender.setCompanyId(page.getCompanyId());
2580                    subscriptionSender.setContextAttributes(
2581                            "[$DIFFS_URL$]",
2582                            getDiffsURL(node, page, previousVersionPage, serviceContext),
2583                            "[$NODE_NAME$]", node.getName(), "[$PAGE_DATE_UPDATE$]",
2584                            page.getModifiedDate(), "[$PAGE_ID$]", page.getPageId(),
2585                            "[$PAGE_SUMMARY$]", page.getSummary(), "[$PAGE_TITLE$]",
2586                            page.getTitle(), "[$PAGE_URL$]",
2587                            getPageURL(node, page, serviceContext));
2588                    subscriptionSender.setContextAttribute(
2589                            "[$PAGE_CONTENT$]", pageContent, false);
2590                    subscriptionSender.setContextAttribute(
2591                            "[$PAGE_DIFFS$]", replaceStyles(pageDiffs), false);
2592                    subscriptionSender.setContextUserPrefix("PAGE");
2593                    subscriptionSender.setFrom(fromAddress, fromName);
2594                    subscriptionSender.setHtmlFormat(true);
2595                    subscriptionSender.setMailId(
2596                            "wiki_page", page.getNodeId(), page.getPageId());
2597                    subscriptionSender.setPortletId(PortletKeys.WIKI);
2598                    subscriptionSender.setReplyToAddress(fromAddress);
2599                    subscriptionSender.setScopeGroupId(node.getGroupId());
2600                    subscriptionSender.setServiceContext(serviceContext);
2601                    subscriptionSender.setSubject(subject);
2602                    subscriptionSender.setUserId(page.getUserId());
2603    
2604                    subscriptionSender.addPersistedSubscribers(
2605                            WikiNode.class.getName(), node.getNodeId());
2606                    subscriptionSender.addPersistedSubscribers(
2607                            WikiPage.class.getName(), page.getResourcePrimKey());
2608    
2609                    subscriptionSender.flushNotificationsAsync();
2610            }
2611    
2612            protected void populateServiceContext(
2613                            ServiceContext serviceContext, WikiPage page)
2614                    throws PortalException, SystemException {
2615    
2616                    long[] assetCategoryIds = assetCategoryLocalService.getCategoryIds(
2617                            WikiPage.class.getName(), page.getResourcePrimKey());
2618    
2619                    serviceContext.setAssetCategoryIds(assetCategoryIds);
2620    
2621                    AssetEntry assetEntry = assetEntryLocalService.getEntry(
2622                            WikiPage.class.getName(), page.getResourcePrimKey());
2623    
2624                    List<AssetLink> assetLinks = assetLinkLocalService.getLinks(
2625                            assetEntry.getEntryId());
2626    
2627                    long[] assetLinkEntryIds = StringUtil.split(
2628                            ListUtil.toString(assetLinks, AssetLink.ENTRY_ID2_ACCESSOR), 0L);
2629    
2630                    serviceContext.setAssetLinkEntryIds(assetLinkEntryIds);
2631    
2632                    String[] assetTagNames = assetTagLocalService.getTagNames(
2633                            WikiPage.class.getName(), page.getResourcePrimKey());
2634    
2635                    serviceContext.setAssetTagNames(assetTagNames);
2636    
2637                    ExpandoBridge expandoBridge = page.getExpandoBridge();
2638    
2639                    serviceContext.setExpandoBridgeAttributes(
2640                            expandoBridge.getAttributes());
2641            }
2642    
2643            protected String replaceStyles(String html) {
2644                    return StringUtil.replace(
2645                            html,
2646                            new String[] {
2647                                    "class=\"diff-html-added\"", "class=\"diff-html-removed\"",
2648                                    "class=\"diff-html-changed\"",
2649                                    "changeType=\"diff-added-image\"",
2650                                    "changeType=\"diff-removed-image\"",
2651                                    "changeType=\"diff-changed-image\""
2652                            },
2653                            new String[] {
2654                                    "style=\"background-color: #CFC;\"",
2655                                    "style=\"background-color: #FDC6C6; text-decoration: " +
2656                                            "line-through;\"",
2657                                    "style=\"border-bottom: 2px dotted blue;\"",
2658                                    "style=\"border: 10px solid #CFC;\"",
2659                                    "style=\"border: 10px solid #FDC6C6;\"",
2660                                    "style=\"border: 10px solid blue;\""
2661                            }
2662                    );
2663            }
2664    
2665            protected void validate(long nodeId, String content, String format)
2666                    throws PortalException {
2667    
2668                    if (!WikiUtil.validate(nodeId, content, format)) {
2669                            throw new PageContentException();
2670                    }
2671            }
2672    
2673            protected void validate(
2674                            String title, long nodeId, String content, String format)
2675                    throws PortalException, SystemException {
2676    
2677                    if (Validator.isNull(title)) {
2678                            throw new PageTitleException();
2679                    }
2680    
2681                    if (isUsedTitle(nodeId, title)) {
2682                            throw new DuplicatePageException("{nodeId=" + nodeId + "}");
2683                    }
2684    
2685                    validateTitle(title);
2686    
2687                    validate(nodeId, content, format);
2688            }
2689    
2690    }