1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.wiki.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.configuration.Filter;
28  import com.liferay.portal.kernel.log.Log;
29  import com.liferay.portal.kernel.log.LogFactoryUtil;
30  import com.liferay.portal.kernel.search.BooleanClauseOccur;
31  import com.liferay.portal.kernel.search.BooleanQuery;
32  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
33  import com.liferay.portal.kernel.search.Field;
34  import com.liferay.portal.kernel.search.Hits;
35  import com.liferay.portal.kernel.search.SearchEngineUtil;
36  import com.liferay.portal.kernel.search.SearchException;
37  import com.liferay.portal.kernel.search.TermQuery;
38  import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
39  import com.liferay.portal.kernel.util.GetterUtil;
40  import com.liferay.portal.kernel.util.InstancePool;
41  import com.liferay.portal.kernel.util.Validator;
42  import com.liferay.portal.model.ResourceConstants;
43  import com.liferay.portal.model.User;
44  import com.liferay.portal.service.ServiceContext;
45  import com.liferay.portal.util.PropsKeys;
46  import com.liferay.portal.util.PropsUtil;
47  import com.liferay.portlet.wiki.DuplicateNodeNameException;
48  import com.liferay.portlet.wiki.NodeNameException;
49  import com.liferay.portlet.wiki.importers.WikiImporter;
50  import com.liferay.portlet.wiki.model.WikiNode;
51  import com.liferay.portlet.wiki.model.WikiPage;
52  import com.liferay.portlet.wiki.service.base.WikiNodeLocalServiceBaseImpl;
53  import com.liferay.portlet.wiki.util.Indexer;
54  
55  import java.io.File;
56  
57  import java.util.Date;
58  import java.util.HashMap;
59  import java.util.Iterator;
60  import java.util.List;
61  import java.util.Map;
62  
63  /**
64   * <a href="WikiNodeLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
65   *
66   * @author Brian Wing Shun Chan
67   * @author Charles May
68   * @author Raymond Augé
69   *
70   */
71  public class WikiNodeLocalServiceImpl extends WikiNodeLocalServiceBaseImpl {
72  
73      public WikiNode addNode(
74              long userId, String name, String description,
75              ServiceContext serviceContext)
76          throws PortalException, SystemException {
77  
78          return addNode(null, userId, name, description, serviceContext);
79      }
80  
81      public WikiNode addNode(
82              String uuid, long userId, String name, String description,
83              ServiceContext serviceContext)
84          throws PortalException, SystemException {
85  
86          // Node
87  
88          User user = userPersistence.findByPrimaryKey(userId);
89          long groupId = serviceContext.getScopeGroupId();
90          Date now = new Date();
91  
92          validate(groupId, name);
93  
94          long nodeId = counterLocalService.increment();
95  
96          WikiNode node = wikiNodePersistence.create(nodeId);
97  
98          node.setUuid(uuid);
99          node.setGroupId(groupId);
100         node.setCompanyId(user.getCompanyId());
101         node.setUserId(user.getUserId());
102         node.setUserName(user.getFullName());
103         node.setCreateDate(now);
104         node.setModifiedDate(now);
105         node.setName(name);
106         node.setDescription(description);
107 
108         wikiNodePersistence.update(node, false);
109 
110         // Resources
111 
112         if (serviceContext.getAddCommunityPermissions() ||
113             serviceContext.getAddGuestPermissions()) {
114 
115             addNodeResources(
116                 node, serviceContext.getAddCommunityPermissions(),
117                 serviceContext.getAddGuestPermissions());
118         }
119         else {
120             addNodeResources(
121                 node, serviceContext.getCommunityPermissions(),
122                 serviceContext.getGuestPermissions());
123         }
124 
125         return node;
126     }
127 
128     public void addNodeResources(
129             long nodeId, boolean addCommunityPermissions,
130             boolean addGuestPermissions)
131         throws PortalException, SystemException {
132 
133         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
134 
135         addNodeResources(node, addCommunityPermissions, addGuestPermissions);
136     }
137 
138     public void addNodeResources(
139             WikiNode node, boolean addCommunityPermissions,
140             boolean addGuestPermissions)
141         throws PortalException, SystemException {
142 
143         resourceLocalService.addResources(
144             node.getCompanyId(), node.getGroupId(), node.getUserId(),
145             WikiNode.class.getName(), node.getNodeId(), false,
146             addCommunityPermissions, addGuestPermissions);
147     }
148 
149     public void addNodeResources(
150             long nodeId, String[] communityPermissions,
151             String[] guestPermissions)
152         throws PortalException, SystemException {
153 
154         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
155 
156         addNodeResources(node, communityPermissions, guestPermissions);
157     }
158 
159     public void addNodeResources(
160             WikiNode node, String[] communityPermissions,
161             String[] guestPermissions)
162         throws PortalException, SystemException {
163 
164         resourceLocalService.addModelResources(
165             node.getCompanyId(), node.getGroupId(), node.getUserId(),
166             WikiNode.class.getName(), node.getNodeId(), communityPermissions,
167             guestPermissions);
168     }
169 
170     public void deleteNode(long nodeId)
171         throws PortalException, SystemException {
172 
173         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
174 
175         deleteNode(node);
176     }
177 
178     public void deleteNode(WikiNode node)
179         throws PortalException, SystemException {
180 
181         // Indexer
182 
183         try {
184             Indexer.deletePages(node.getCompanyId(), node.getNodeId());
185         }
186         catch (SearchException se) {
187             _log.error("Deleting index " + node.getNodeId(), se);
188         }
189 
190         // Subscriptions
191 
192         subscriptionLocalService.deleteSubscriptions(
193             node.getCompanyId(), WikiNode.class.getName(), node.getNodeId());
194 
195         // Pages
196 
197         wikiPageLocalService.deletePages(node.getNodeId());
198 
199         // Resources
200 
201         resourceLocalService.deleteResource(
202             node.getCompanyId(), WikiNode.class.getName(),
203             ResourceConstants.SCOPE_INDIVIDUAL, node.getNodeId());
204 
205         // Node
206 
207         wikiNodePersistence.remove(node);
208     }
209 
210     public void deleteNodes(long groupId)
211         throws PortalException, SystemException {
212 
213         Iterator<WikiNode> itr = wikiNodePersistence.findByGroupId(
214             groupId).iterator();
215 
216         while (itr.hasNext()) {
217             WikiNode node = itr.next();
218 
219             deleteNode(node);
220         }
221     }
222 
223     public WikiNode getNode(long nodeId)
224         throws PortalException, SystemException {
225 
226         return wikiNodePersistence.findByPrimaryKey(nodeId);
227     }
228 
229     public WikiNode getNode(long groupId, String nodeName)
230         throws PortalException, SystemException {
231 
232         return wikiNodePersistence.findByG_N(groupId, nodeName);
233     }
234 
235     public List<WikiNode> getNodes(long groupId) throws SystemException {
236         return wikiNodePersistence.findByGroupId(groupId);
237     }
238 
239     public List<WikiNode> getNodes(long groupId, int start, int end)
240         throws SystemException {
241 
242         return wikiNodePersistence.findByGroupId(groupId, start, end);
243     }
244 
245     public int getNodesCount(long groupId) throws SystemException {
246         return wikiNodePersistence.countByGroupId(groupId);
247     }
248 
249     public void importPages(
250             long userId, long nodeId, String importer, File[] files,
251             Map<String, String[]> options)
252         throws PortalException, SystemException {
253 
254         WikiNode node = getNode(nodeId);
255 
256         getWikiImporter(importer).importPages(userId, node, files, options);
257     }
258 
259     public void reIndex(String[] ids) throws SystemException {
260         if (SearchEngineUtil.isIndexReadOnly()) {
261             return;
262         }
263 
264         long companyId = GetterUtil.getLong(ids[0]);
265 
266         try {
267             Iterator<WikiNode> nodesItr = wikiNodePersistence.findByCompanyId(
268                 companyId).iterator();
269 
270             while (nodesItr.hasNext()) {
271                 WikiNode node = nodesItr.next();
272 
273                 long nodeId = node.getNodeId();
274 
275                 Iterator<WikiPage> pagesItr = wikiPagePersistence.findByN_H(
276                     nodeId, true).iterator();
277 
278                 while (pagesItr.hasNext()) {
279                     WikiPage page = pagesItr.next();
280 
281                     long groupId = node.getGroupId();
282                     long resourcePrimKey = page.getResourcePrimKey();
283                     String title = page.getTitle();
284                     String content = page.getContent();
285                     Date modifiedDate = page.getModifiedDate();
286 
287                     String[] tagsEntries = tagsEntryLocalService.getEntryNames(
288                         WikiPage.class.getName(), resourcePrimKey);
289 
290                     try {
291                         Indexer.updatePage(
292                             companyId, groupId, resourcePrimKey, nodeId, title,
293                             content, modifiedDate, tagsEntries,
294                             page.getExpandoBridge());
295                     }
296                     catch (SearchException se) {
297                         _log.error("Reindexing " + page.getPrimaryKey(), se);
298                     }
299                 }
300             }
301         }
302         catch (SystemException se) {
303             throw se;
304         }
305         catch (Exception e) {
306             throw new SystemException(e);
307         }
308     }
309 
310     public Hits search(
311             long companyId, long groupId, long userId, long[] nodeIds,
312             String keywords, int start, int end)
313         throws SystemException {
314 
315         try {
316             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
317 
318             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
319 
320             if (groupId > 0) {
321                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
322             }
323 
324             if ((nodeIds != null) && (nodeIds.length > 0)) {
325                 BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create();
326 
327                 for (long nodeId : nodeIds) {
328                     if (userId > 0) {
329                         try {
330                             wikiNodeService.getNode(nodeId);
331                         }
332                         catch (Exception e) {
333                             continue;
334                         }
335                     }
336 
337                     TermQuery termQuery = TermQueryFactoryUtil.create(
338                         "nodeId", nodeId);
339 
340                     nodeIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
341                 }
342 
343                 contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
344             }
345 
346             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
347 
348             if (Validator.isNotNull(keywords)) {
349                 searchQuery.addTerm(Field.TITLE, keywords);
350                 searchQuery.addTerm(Field.CONTENT, keywords);
351                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
352             }
353 
354             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
355 
356             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
357 
358             if (searchQuery.clauses().size() > 0) {
359                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
360             }
361 
362             return SearchEngineUtil.search(
363                 companyId, groupId, userId, WikiPage.class.getName(), fullQuery,
364                 start, end);
365         }
366         catch (Exception e) {
367             throw new SystemException(e);
368         }
369     }
370 
371     public void subscribeNode(long userId, long nodeId)
372         throws PortalException, SystemException {
373 
374         subscriptionLocalService.addSubscription(
375             userId, WikiNode.class.getName(), nodeId);
376     }
377 
378     public void unsubscribeNode(long userId, long nodeId)
379         throws PortalException, SystemException {
380 
381         subscriptionLocalService.deleteSubscription(
382             userId, WikiNode.class.getName(), nodeId);
383     }
384 
385     public WikiNode updateNode(long nodeId, String name, String description)
386         throws PortalException, SystemException {
387 
388         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
389 
390         validate(nodeId, node.getGroupId(), name);
391 
392         node.setModifiedDate(new Date());
393         node.setName(name);
394         node.setDescription(description);
395 
396         wikiNodePersistence.update(node, false);
397 
398         return node;
399     }
400 
401     protected WikiImporter getWikiImporter(String importer)
402         throws SystemException {
403 
404         WikiImporter wikiImporter = _wikiImporters.get(importer);
405 
406         if (wikiImporter == null) {
407             String importerClass = PropsUtil.get(
408                 PropsKeys.WIKI_IMPORTERS_CLASS, new Filter(importer));
409 
410             if (importerClass != null) {
411                 wikiImporter = (WikiImporter)InstancePool.get(importerClass);
412 
413                 _wikiImporters.put(importer, wikiImporter);
414             }
415 
416             if (importer == null) {
417                 throw new SystemException(
418                     "Unable to instantiate wiki importer class " +
419                         importerClass);
420             }
421         }
422 
423         return wikiImporter;
424     }
425 
426     protected void validate(long groupId, String name)
427         throws PortalException, SystemException {
428 
429         validate(0, groupId, name);
430     }
431 
432     protected void validate(long nodeId, long groupId, String name)
433         throws PortalException, SystemException {
434 
435         if (name.equalsIgnoreCase("tag")) {
436             throw new NodeNameException(name + " is reserved");
437         }
438 
439         if (!Validator.isName(name)) {
440             throw new NodeNameException();
441         }
442 
443         WikiNode node = wikiNodePersistence.fetchByG_N(groupId, name);
444 
445         if ((node != null) && (node.getNodeId() != nodeId)) {
446             throw new DuplicateNodeNameException();
447         }
448     }
449 
450     private static Log _log =
451         LogFactoryUtil.getLog(WikiNodeLocalServiceImpl.class);
452 
453     private Map<String, WikiImporter> _wikiImporters =
454         new HashMap<String, WikiImporter>();
455 
456 }