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