001    /**
002     * Copyright (c) 2000-present 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.configuration.Filter;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.Indexer;
023    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
024    import com.liferay.portal.kernel.systemevent.SystemEvent;
025    import com.liferay.portal.kernel.util.InstanceFactory;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.UnicodeProperties;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.workflow.WorkflowConstants;
032    import com.liferay.portal.model.Group;
033    import com.liferay.portal.model.ResourceConstants;
034    import com.liferay.portal.model.SystemEventConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
037    import com.liferay.portal.service.ServiceContext;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portal.util.PropsUtil;
040    import com.liferay.portal.util.PropsValues;
041    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
042    import com.liferay.portlet.trash.model.TrashEntry;
043    import com.liferay.portlet.trash.util.TrashUtil;
044    import com.liferay.portlet.wiki.DuplicateNodeNameException;
045    import com.liferay.portlet.wiki.NodeNameException;
046    import com.liferay.portlet.wiki.importers.WikiImporter;
047    import com.liferay.portlet.wiki.model.WikiNode;
048    import com.liferay.portlet.wiki.model.WikiPage;
049    import com.liferay.portlet.wiki.service.base.WikiNodeLocalServiceBaseImpl;
050    
051    import java.io.InputStream;
052    
053    import java.util.ArrayList;
054    import java.util.Date;
055    import java.util.HashMap;
056    import java.util.List;
057    import java.util.Map;
058    
059    /**
060     * Provides the local service for accessing, adding, deleting, importing,
061     * subscription handling of, trash handling of, and updating wiki nodes.
062     *
063     * @author Brian Wing Shun Chan
064     * @author Charles May
065     * @author Raymond Aug??
066     */
067    public class WikiNodeLocalServiceImpl extends WikiNodeLocalServiceBaseImpl {
068    
069            @Override
070            public WikiNode addDefaultNode(long userId, ServiceContext serviceContext)
071                    throws PortalException {
072    
073                    return addNode(
074                            userId, PropsValues.WIKI_INITIAL_NODE_NAME, StringPool.BLANK,
075                            serviceContext);
076            }
077    
078            @Override
079            public WikiNode addNode(
080                            long userId, String name, String description,
081                            ServiceContext serviceContext)
082                    throws PortalException {
083    
084                    // Node
085    
086                    User user = userPersistence.findByPrimaryKey(userId);
087                    long groupId = serviceContext.getScopeGroupId();
088                    Date now = new Date();
089    
090                    validate(groupId, name);
091    
092                    long nodeId = counterLocalService.increment();
093    
094                    WikiNode node = wikiNodePersistence.create(nodeId);
095    
096                    node.setUuid(serviceContext.getUuid());
097                    node.setGroupId(groupId);
098                    node.setCompanyId(user.getCompanyId());
099                    node.setUserId(user.getUserId());
100                    node.setUserName(user.getFullName());
101                    node.setCreateDate(serviceContext.getCreateDate(now));
102                    node.setModifiedDate(serviceContext.getModifiedDate(now));
103                    node.setName(name);
104                    node.setDescription(description);
105    
106                    try {
107                            wikiNodePersistence.update(node);
108                    }
109                    catch (SystemException se) {
110                            if (_log.isWarnEnabled()) {
111                                    _log.warn(
112                                            "Add failed, fetch {groupId=" + groupId + ", name=" +
113                                                    name + "}");
114                            }
115    
116                            node = wikiNodePersistence.fetchByG_N(groupId, name, false);
117    
118                            if (node == null) {
119                                    throw se;
120                            }
121    
122                            return node;
123                    }
124    
125                    // Resources
126    
127                    if (serviceContext.isAddGroupPermissions() ||
128                            serviceContext.isAddGuestPermissions()) {
129    
130                            addNodeResources(
131                                    node, serviceContext.isAddGroupPermissions(),
132                                    serviceContext.isAddGuestPermissions());
133                    }
134                    else {
135                            addNodeResources(
136                                    node, serviceContext.getGroupPermissions(),
137                                    serviceContext.getGuestPermissions());
138                    }
139    
140                    return node;
141            }
142    
143            @Override
144            public void addNodeResources(
145                            long nodeId, boolean addGroupPermissions,
146                            boolean addGuestPermissions)
147                    throws PortalException {
148    
149                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
150    
151                    addNodeResources(node, addGroupPermissions, addGuestPermissions);
152            }
153    
154            @Override
155            public void addNodeResources(
156                            long nodeId, String[] groupPermissions, String[] guestPermissions)
157                    throws PortalException {
158    
159                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
160    
161                    addNodeResources(node, groupPermissions, guestPermissions);
162            }
163    
164            @Override
165            public void addNodeResources(
166                            WikiNode node, boolean addGroupPermissions,
167                            boolean addGuestPermissions)
168                    throws PortalException {
169    
170                    resourceLocalService.addResources(
171                            node.getCompanyId(), node.getGroupId(), node.getUserId(),
172                            WikiNode.class.getName(), node.getNodeId(), false,
173                            addGroupPermissions, addGuestPermissions);
174            }
175    
176            @Override
177            public void addNodeResources(
178                            WikiNode node, String[] groupPermissions, String[] guestPermissions)
179                    throws PortalException {
180    
181                    resourceLocalService.addModelResources(
182                            node.getCompanyId(), node.getGroupId(), node.getUserId(),
183                            WikiNode.class.getName(), node.getNodeId(), groupPermissions,
184                            guestPermissions);
185            }
186    
187            @Override
188            public void deleteNode(long nodeId) throws PortalException {
189                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
190    
191                    wikiNodeLocalService.deleteNode(node);
192            }
193    
194            @Override
195            @SystemEvent(
196                    action = SystemEventConstants.ACTION_SKIP,
197                    type = SystemEventConstants.TYPE_DELETE)
198            public void deleteNode(WikiNode node) throws PortalException {
199    
200                    // Pages
201    
202                    wikiPageLocalService.deletePages(node.getNodeId());
203    
204                    // Node
205    
206                    wikiNodePersistence.remove(node);
207    
208                    // Resources
209    
210                    resourceLocalService.deleteResource(
211                            node.getCompanyId(), WikiNode.class.getName(),
212                            ResourceConstants.SCOPE_INDIVIDUAL, node.getNodeId());
213    
214                    // Attachments
215    
216                    long folderId = node.getAttachmentsFolderId();
217    
218                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
219                            PortletFileRepositoryUtil.deletePortletFolder(folderId);
220                    }
221    
222                    // Subscriptions
223    
224                    subscriptionLocalService.deleteSubscriptions(
225                            node.getCompanyId(), WikiNode.class.getName(), node.getNodeId());
226    
227                    if (node.isInTrash()) {
228                            node.setName(TrashUtil.getOriginalTitle(node.getName()));
229    
230                            // Trash
231    
232                            trashEntryLocalService.deleteEntry(
233                                    WikiNode.class.getName(), node.getNodeId());
234    
235                            // Indexer
236    
237                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
238                                    WikiNode.class);
239    
240                            indexer.delete(node);
241                    }
242            }
243    
244            @Override
245            public void deleteNodes(long groupId) throws PortalException {
246                    List<WikiNode> nodes = wikiNodePersistence.findByGroupId(groupId);
247    
248                    for (WikiNode node : nodes) {
249                            wikiNodeLocalService.deleteNode(node);
250                    }
251    
252                    PortletFileRepositoryUtil.deletePortletRepository(
253                            groupId, PortletKeys.WIKI);
254            }
255    
256            @Override
257            public WikiNode fetchNode(long groupId, String name) {
258                    return wikiNodePersistence.fetchByG_N(groupId, name);
259            }
260    
261            @Override
262            public WikiNode fetchNodeByUuidAndGroupId(String uuid, long groupId) {
263                    return wikiNodePersistence.fetchByUUID_G(uuid, groupId);
264            }
265    
266            @Override
267            public List<WikiNode> getCompanyNodes(long companyId, int start, int end) {
268                    return wikiNodePersistence.findByC_S(
269                            companyId, WorkflowConstants.STATUS_APPROVED, start, end);
270            }
271    
272            @Override
273            public List<WikiNode> getCompanyNodes(
274                    long companyId, int status, int start, int end) {
275    
276                    return wikiNodePersistence.findByC_S(companyId, status, start, end);
277            }
278    
279            @Override
280            public int getCompanyNodesCount(long companyId) {
281                    return wikiNodePersistence.countByC_S(
282                            companyId, WorkflowConstants.STATUS_APPROVED);
283            }
284    
285            @Override
286            public int getCompanyNodesCount(long companyId, int status) {
287                    return wikiNodePersistence.countByC_S(companyId, status);
288            }
289    
290            @Override
291            public WikiNode getNode(long nodeId) throws PortalException {
292                    return wikiNodePersistence.findByPrimaryKey(nodeId);
293            }
294    
295            @Override
296            public WikiNode getNode(long groupId, String nodeName)
297                    throws PortalException {
298    
299                    return wikiNodePersistence.findByG_N(groupId, nodeName);
300            }
301    
302            @Override
303            public List<WikiNode> getNodes(long groupId) throws PortalException {
304                    return getNodes(groupId, WorkflowConstants.STATUS_APPROVED);
305            }
306    
307            @Override
308            public List<WikiNode> getNodes(long groupId, int status)
309                    throws PortalException {
310    
311                    List<WikiNode> nodes = wikiNodePersistence.findByG_S(groupId, status);
312    
313                    if (nodes.isEmpty()) {
314                            nodes = addDefaultNode(groupId);
315                    }
316    
317                    return nodes;
318            }
319    
320            @Override
321            public List<WikiNode> getNodes(long groupId, int start, int end)
322                    throws PortalException {
323    
324                    return getNodes(groupId, WorkflowConstants.STATUS_APPROVED, start, end);
325            }
326    
327            @Override
328            public List<WikiNode> getNodes(long groupId, int status, int start, int end)
329                    throws PortalException {
330    
331                    List<WikiNode> nodes = wikiNodePersistence.findByG_S(
332                            groupId, status, start, end);
333    
334                    if (nodes.isEmpty()) {
335                            nodes = addDefaultNode(groupId);
336                    }
337    
338                    return nodes;
339            }
340    
341            @Override
342            public int getNodesCount(long groupId) {
343                    return wikiNodePersistence.countByG_S(
344                            groupId, WorkflowConstants.STATUS_APPROVED);
345            }
346    
347            @Override
348            public int getNodesCount(long groupId, int status) {
349                    return wikiNodePersistence.countByG_S(groupId, status);
350            }
351    
352            @Override
353            public void importPages(
354                            long userId, long nodeId, String importer,
355                            InputStream[] inputStreams, Map<String, String[]> options)
356                    throws PortalException {
357    
358                    WikiNode node = getNode(nodeId);
359    
360                    WikiImporter wikiImporter = getWikiImporter(importer);
361    
362                    wikiImporter.importPages(userId, node, inputStreams, options);
363            }
364    
365            @Override
366            public WikiNode moveNodeToTrash(long userId, long nodeId)
367                    throws PortalException {
368    
369                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
370    
371                    return moveNodeToTrash(userId, node);
372            }
373    
374            @Override
375            public WikiNode moveNodeToTrash(long userId, WikiNode node)
376                    throws PortalException {
377    
378                    // Node
379    
380                    int oldStatus = node.getStatus();
381    
382                    node = updateStatus(
383                            userId, node, WorkflowConstants.STATUS_IN_TRASH,
384                            new ServiceContext());
385    
386                    // Trash
387    
388                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
389    
390                    typeSettingsProperties.put("title", node.getName());
391    
392                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
393                            userId, node.getGroupId(), WikiNode.class.getName(),
394                            node.getNodeId(), node.getUuid(), null, oldStatus, null,
395                            typeSettingsProperties);
396    
397                    node.setName(TrashUtil.getTrashTitle(trashEntry.getEntryId()));
398    
399                    wikiNodePersistence.update(node);
400    
401                    // Pages
402    
403                    moveDependentsToTrash(node.getNodeId(), trashEntry.getEntryId());
404    
405                    return node;
406            }
407    
408            @Override
409            public void restoreNodeFromTrash(long userId, WikiNode node)
410                    throws PortalException {
411    
412                    // Node
413    
414                    node.setName(TrashUtil.getOriginalTitle(node.getName()));
415    
416                    wikiNodePersistence.update(node);
417    
418                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
419                            WikiNode.class.getName(), node.getNodeId());
420    
421                    updateStatus(
422                            userId, node, trashEntry.getStatus(), new ServiceContext());
423    
424                    // Pages
425    
426                    restoreDependentsFromTrash(userId, node.getNodeId());
427    
428                    // Trash
429    
430                    trashEntryLocalService.deleteEntry(trashEntry);
431            }
432    
433            @Override
434            public void subscribeNode(long userId, long nodeId) throws PortalException {
435                    WikiNode node = getNode(nodeId);
436    
437                    subscriptionLocalService.addSubscription(
438                            userId, node.getGroupId(), WikiNode.class.getName(), nodeId);
439            }
440    
441            @Override
442            public void unsubscribeNode(long userId, long nodeId)
443                    throws PortalException {
444    
445                    subscriptionLocalService.deleteSubscription(
446                            userId, WikiNode.class.getName(), nodeId);
447            }
448    
449            @Override
450            public WikiNode updateNode(
451                            long nodeId, String name, String description,
452                            ServiceContext serviceContext)
453                    throws PortalException {
454    
455                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
456    
457                    validate(nodeId, node.getGroupId(), name);
458    
459                    node.setModifiedDate(serviceContext.getModifiedDate(null));
460                    node.setName(name);
461                    node.setDescription(description);
462    
463                    wikiNodePersistence.update(node);
464    
465                    return node;
466            }
467    
468            @Override
469            public WikiNode updateStatus(
470                            long userId, WikiNode node, int status,
471                            ServiceContext serviceContext)
472                    throws PortalException {
473    
474                    // Node
475    
476                    User user = userPersistence.findByPrimaryKey(userId);
477    
478                    Date now = new Date();
479    
480                    node.setStatus(status);
481                    node.setStatusByUserId(userId);
482                    node.setStatusByUserName(user.getFullName());
483                    node.setStatusDate(now);
484    
485                    wikiNodePersistence.update(node);
486    
487                    // Indexer
488    
489                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
490                            WikiNode.class);
491    
492                    indexer.reindex(node);
493    
494                    return node;
495            }
496    
497            protected List<WikiNode> addDefaultNode(long groupId)
498                    throws PortalException {
499    
500                    Group group = groupPersistence.findByPrimaryKey(groupId);
501    
502                    long defaultUserId = userLocalService.getDefaultUserId(
503                            group.getCompanyId());
504    
505                    ServiceContext serviceContext = new ServiceContext();
506    
507                    serviceContext.setAddGroupPermissions(true);
508                    serviceContext.setAddGuestPermissions(true);
509                    serviceContext.setScopeGroupId(groupId);
510    
511                    WikiNode node = wikiNodeLocalService.addDefaultNode(
512                            defaultUserId, serviceContext);
513    
514                    List<WikiNode> nodes = new ArrayList<WikiNode>(1);
515    
516                    nodes.add(node);
517    
518                    return nodes;
519            }
520    
521            protected WikiImporter getWikiImporter(String importer) {
522                    WikiImporter wikiImporter = _wikiImporters.get(importer);
523    
524                    if (wikiImporter == null) {
525                            String importerClassName = PropsUtil.get(
526                                    PropsKeys.WIKI_IMPORTERS_CLASS, new Filter(importer));
527    
528                            if (importerClassName != null) {
529                                    try {
530                                            wikiImporter = (WikiImporter)InstanceFactory.newInstance(
531                                                    getClassLoader(), importerClassName);
532    
533                                            _wikiImporters.put(importer, wikiImporter);
534                                    }
535                                    catch (Exception e) {
536                                            throw new SystemException(
537                                                    "Unable to instantiate wiki importer class " +
538                                                            importerClassName,
539                                                    e);
540                                    }
541                            }
542    
543                            if (importer == null) {
544                                    throw new SystemException(
545                                            "Unable to instantiate wiki importer class " +
546                                                    importerClassName);
547                            }
548                    }
549    
550                    return wikiImporter;
551            }
552    
553            protected void moveDependentsToTrash(long nodeId, long trashEntryId)
554                    throws PortalException {
555    
556                    List<WikiPage> pages = wikiPagePersistence.findByNodeId(nodeId);
557    
558                    for (WikiPage page : pages) {
559                            wikiPageLocalService.moveDependentToTrash(page, trashEntryId);
560                    }
561            }
562    
563            protected void restoreDependentsFromTrash(long userId, long nodeId)
564                    throws PortalException {
565    
566                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
567    
568                    for (WikiPage page : pages) {
569                            if (!page.isInTrashImplicitly()) {
570                                    continue;
571                            }
572    
573                            wikiPageLocalService.restorePageFromTrash(userId, page);
574                    }
575            }
576    
577            protected void validate(long nodeId, long groupId, String name)
578                    throws PortalException {
579    
580                    if (StringUtil.equalsIgnoreCase(name, "tag")) {
581                            throw new NodeNameException(name + " is reserved");
582                    }
583    
584                    if (Validator.isNull(name)) {
585                            throw new NodeNameException();
586                    }
587    
588                    WikiNode node = wikiNodePersistence.fetchByG_N(groupId, name);
589    
590                    if ((node != null) && (node.getNodeId() != nodeId)) {
591                            throw new DuplicateNodeNameException("{nodeId=" + nodeId + "}");
592                    }
593            }
594    
595            protected void validate(long groupId, String name) throws PortalException {
596                    validate(0, groupId, name);
597            }
598    
599            private static final Log _log = LogFactoryUtil.getLog(
600                    WikiNodeLocalServiceImpl.class);
601    
602            private final Map<String, WikiImporter> _wikiImporters =
603                    new HashMap<String, WikiImporter>();
604    
605    }