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