1   /**
2    * Copyright (c) 2000-2008 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.search.BooleanClauseOccur;
29  import com.liferay.portal.kernel.search.BooleanQuery;
30  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
31  import com.liferay.portal.kernel.search.Field;
32  import com.liferay.portal.kernel.search.Hits;
33  import com.liferay.portal.kernel.search.SearchEngineUtil;
34  import com.liferay.portal.kernel.search.SearchException;
35  import com.liferay.portal.kernel.search.TermQuery;
36  import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
37  import com.liferay.portal.kernel.util.GetterUtil;
38  import com.liferay.portal.kernel.util.InstancePool;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.model.ResourceConstants;
41  import com.liferay.portal.model.User;
42  import com.liferay.portal.util.PortalUtil;
43  import com.liferay.portal.util.PropsKeys;
44  import com.liferay.portal.util.PropsUtil;
45  import com.liferay.portlet.wiki.DuplicateNodeNameException;
46  import com.liferay.portlet.wiki.NodeNameException;
47  import com.liferay.portlet.wiki.importers.WikiImporter;
48  import com.liferay.portlet.wiki.model.WikiNode;
49  import com.liferay.portlet.wiki.model.WikiPage;
50  import com.liferay.portlet.wiki.service.base.WikiNodeLocalServiceBaseImpl;
51  import com.liferay.portlet.wiki.util.Indexer;
52  
53  import java.io.File;
54  
55  import java.util.Date;
56  import java.util.HashMap;
57  import java.util.Iterator;
58  import java.util.List;
59  import java.util.Map;
60  
61  import org.apache.commons.logging.Log;
62  import org.apache.commons.logging.LogFactory;
63  
64  /**
65   * <a href="WikiNodeLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
66   *
67   * @author Brian Wing Shun Chan
68   * @author Charles May
69   *
70   */
71  public class WikiNodeLocalServiceImpl extends WikiNodeLocalServiceBaseImpl {
72  
73      public WikiNode addNode(
74              long userId, long plid, String name, String description,
75              boolean addCommunityPermissions, boolean addGuestPermissions)
76          throws PortalException, SystemException {
77  
78          return addNode(
79              null, userId, plid, name, description,
80              Boolean.valueOf(addCommunityPermissions),
81              Boolean.valueOf(addGuestPermissions), null, null);
82      }
83  
84      public WikiNode addNode(
85              String uuid, long userId, long plid, String name,
86              String description, boolean addCommunityPermissions,
87              boolean addGuestPermissions)
88          throws PortalException, SystemException {
89  
90          return addNode(
91              uuid, userId, plid, name, description,
92              Boolean.valueOf(addCommunityPermissions),
93              Boolean.valueOf(addGuestPermissions), null, null);
94      }
95  
96      public WikiNode addNode(
97              long userId, long plid, String name, String description,
98              String[] communityPermissions, String[] guestPermissions)
99          throws PortalException, SystemException {
100 
101         return addNode(
102             null, userId, plid, name, description, null, null,
103             communityPermissions, guestPermissions);
104     }
105 
106     public WikiNode addNode(
107             String uuid, long userId, long plid, String name,
108             String description, Boolean addCommunityPermissions,
109             Boolean addGuestPermissions, String[] communityPermissions,
110             String[] guestPermissions)
111         throws PortalException, SystemException {
112 
113         // Node
114 
115         User user = userPersistence.findByPrimaryKey(userId);
116         long groupId = PortalUtil.getScopeGroupId(plid);
117         Date now = new Date();
118 
119         validate(groupId, name);
120 
121         long nodeId = counterLocalService.increment();
122 
123         WikiNode node = wikiNodePersistence.create(nodeId);
124 
125         node.setUuid(uuid);
126         node.setGroupId(groupId);
127         node.setCompanyId(user.getCompanyId());
128         node.setUserId(user.getUserId());
129         node.setUserName(user.getFullName());
130         node.setCreateDate(now);
131         node.setModifiedDate(now);
132         node.setName(name);
133         node.setDescription(description);
134 
135         wikiNodePersistence.update(node, false);
136 
137         // Resources
138 
139         if ((addCommunityPermissions != null) &&
140             (addGuestPermissions != null)) {
141 
142             addNodeResources(
143                 node, addCommunityPermissions.booleanValue(),
144                 addGuestPermissions.booleanValue());
145         }
146         else {
147             addNodeResources(node, communityPermissions, guestPermissions);
148         }
149 
150         return node;
151     }
152 
153     public void addNodeResources(
154             long nodeId, boolean addCommunityPermissions,
155             boolean addGuestPermissions)
156         throws PortalException, SystemException {
157 
158         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
159 
160         addNodeResources(node, addCommunityPermissions, addGuestPermissions);
161     }
162 
163     public void addNodeResources(
164             WikiNode node, boolean addCommunityPermissions,
165             boolean addGuestPermissions)
166         throws PortalException, SystemException {
167 
168         resourceLocalService.addResources(
169             node.getCompanyId(), node.getGroupId(), node.getUserId(),
170             WikiNode.class.getName(), node.getNodeId(), false,
171             addCommunityPermissions, addGuestPermissions);
172     }
173 
174     public void addNodeResources(
175             long nodeId, String[] communityPermissions,
176             String[] guestPermissions)
177         throws PortalException, SystemException {
178 
179         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
180 
181         addNodeResources(node, communityPermissions, guestPermissions);
182     }
183 
184     public void addNodeResources(
185             WikiNode node, String[] communityPermissions,
186             String[] guestPermissions)
187         throws PortalException, SystemException {
188 
189         resourceLocalService.addModelResources(
190             node.getCompanyId(), node.getGroupId(), node.getUserId(),
191             WikiNode.class.getName(), node.getNodeId(), communityPermissions,
192             guestPermissions);
193     }
194 
195     public void deleteNode(long nodeId)
196         throws PortalException, SystemException {
197 
198         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
199 
200         deleteNode(node);
201     }
202 
203     public void deleteNode(WikiNode node)
204         throws PortalException, SystemException {
205 
206         // Indexer
207 
208         try {
209             Indexer.deletePages(node.getCompanyId(), node.getNodeId());
210         }
211         catch (SearchException se) {
212             _log.error("Deleting index " + node.getNodeId(), se);
213         }
214 
215         // Subscriptions
216 
217         subscriptionLocalService.deleteSubscriptions(
218             node.getCompanyId(), WikiNode.class.getName(), node.getNodeId());
219 
220         // Pages
221 
222         wikiPageLocalService.deletePages(node.getNodeId());
223 
224         // Resources
225 
226         resourceLocalService.deleteResource(
227             node.getCompanyId(), WikiNode.class.getName(),
228             ResourceConstants.SCOPE_INDIVIDUAL, node.getNodeId());
229 
230         // Node
231 
232         wikiNodePersistence.remove(node);
233     }
234 
235     public void deleteNodes(long groupId)
236         throws PortalException, SystemException {
237 
238         Iterator<WikiNode> itr = wikiNodePersistence.findByGroupId(
239             groupId).iterator();
240 
241         while (itr.hasNext()) {
242             WikiNode node = itr.next();
243 
244             deleteNode(node);
245         }
246     }
247 
248     public WikiNode getNode(long nodeId)
249         throws PortalException, SystemException {
250 
251         return wikiNodePersistence.findByPrimaryKey(nodeId);
252     }
253 
254     public WikiNode getNode(long groupId, String nodeName)
255         throws PortalException, SystemException {
256 
257         return wikiNodePersistence.findByG_N(groupId, nodeName);
258     }
259 
260     public List<WikiNode> getNodes(long groupId) throws SystemException {
261         return wikiNodePersistence.findByGroupId(groupId);
262     }
263 
264     public List<WikiNode> getNodes(long groupId, int start, int end)
265         throws SystemException {
266 
267         return wikiNodePersistence.findByGroupId(groupId, start, end);
268     }
269 
270     public int getNodesCount(long groupId) throws SystemException {
271         return wikiNodePersistence.countByGroupId(groupId);
272     }
273 
274     public void importPages(
275             long userId, long nodeId, String importer, File[] files,
276             Map<String, String[]> options)
277         throws PortalException, SystemException {
278 
279         WikiNode node = getNode(nodeId);
280 
281         getWikiImporter(importer).importPages(userId, node, files, options);
282     }
283 
284     public void reIndex(String[] ids) throws SystemException {
285         if (SearchEngineUtil.isIndexReadOnly()) {
286             return;
287         }
288 
289         long companyId = GetterUtil.getLong(ids[0]);
290 
291         try {
292             Iterator<WikiNode> nodesItr = wikiNodePersistence.findByCompanyId(
293                 companyId).iterator();
294 
295             while (nodesItr.hasNext()) {
296                 WikiNode node = nodesItr.next();
297 
298                 long nodeId = node.getNodeId();
299 
300                 Iterator<WikiPage> pagesItr = wikiPagePersistence.findByN_H(
301                     nodeId, true).iterator();
302 
303                 while (pagesItr.hasNext()) {
304                     WikiPage page = pagesItr.next();
305 
306                     long groupId = node.getGroupId();
307                     String title = page.getTitle();
308                     String content = page.getContent();
309 
310                     String[] tagsEntries = tagsEntryLocalService.getEntryNames(
311                         WikiPage.class.getName(), page.getResourcePrimKey());
312 
313                     try {
314                         Indexer.updatePage(
315                             companyId, groupId, nodeId, title, content,
316                             tagsEntries);
317                     }
318                     catch (SearchException se) {
319                         _log.error("Reindexing " + page.getPrimaryKey(), se);
320                     }
321                 }
322             }
323         }
324         catch (SystemException se) {
325             throw se;
326         }
327         catch (Exception e) {
328             throw new SystemException(e);
329         }
330     }
331 
332     public Hits search(
333             long companyId, long groupId, long[] nodeIds, String keywords,
334             int start, int end)
335         throws SystemException {
336 
337         try {
338             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
339 
340             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
341 
342             if (groupId > 0) {
343                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
344             }
345 
346             if ((nodeIds != null) && (nodeIds.length > 0)) {
347                 BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create();
348 
349                 for (long nodeId : nodeIds) {
350                     TermQuery termQuery = TermQueryFactoryUtil.create(
351                         Field.ENTRY_CLASS_PK, nodeId);
352 
353                     nodeIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
354                 }
355 
356                 contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
357             }
358 
359             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
360 
361             if (Validator.isNotNull(keywords)) {
362                 searchQuery.addTerm(Field.TITLE, keywords);
363                 searchQuery.addTerm(Field.CONTENT, keywords);
364                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
365             }
366 
367             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
368 
369             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
370 
371             if (searchQuery.clauses().size() > 0) {
372                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
373             }
374 
375             return SearchEngineUtil.search(companyId, fullQuery, start, end);
376         }
377         catch (Exception e) {
378             throw new SystemException(e);
379         }
380     }
381 
382     public void subscribeNode(long userId, long nodeId)
383         throws PortalException, SystemException {
384 
385         subscriptionLocalService.addSubscription(
386             userId, 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(long nodeId, String name, String description)
397         throws PortalException, SystemException {
398 
399         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
400 
401         validate(nodeId, node.getGroupId(), name);
402 
403         node.setModifiedDate(new Date());
404         node.setName(name);
405         node.setDescription(description);
406 
407         wikiNodePersistence.update(node, false);
408 
409         return node;
410     }
411 
412     protected WikiImporter getWikiImporter(String importer)
413         throws SystemException {
414 
415         WikiImporter wikiImporter = _wikiImporters.get(importer);
416 
417         if (wikiImporter == null) {
418             String importerClass = PropsUtil.get(
419                 PropsKeys.WIKI_IMPORTERS_CLASS, new Filter(importer));
420 
421             if (importerClass != null) {
422                 wikiImporter = (WikiImporter)InstancePool.get(importerClass);
423 
424                 _wikiImporters.put(importer, wikiImporter);
425             }
426 
427             if (importer == null) {
428                 throw new SystemException(
429                     "Unable to instantiate wiki importer class " +
430                         importerClass);
431             }
432         }
433 
434         return wikiImporter;
435     }
436 
437     protected void validate(long groupId, String name)
438         throws PortalException, SystemException {
439 
440         validate(0, groupId, name);
441     }
442 
443     protected void validate(long nodeId, long groupId, String name)
444         throws PortalException, SystemException {
445 
446         if (name.equalsIgnoreCase("tag")) {
447             throw new NodeNameException(name + " is reserved");
448         }
449 
450         if (!Validator.isName(name)) {
451             throw new NodeNameException();
452         }
453 
454         WikiNode node = wikiNodePersistence.fetchByG_N(groupId, name);
455 
456         if ((node != null) && (node.getNodeId() != nodeId)) {
457             throw new DuplicateNodeNameException();
458         }
459     }
460 
461     private static Log _log = LogFactory.getLog(WikiNodeLocalServiceImpl.class);
462 
463     private Map<String, WikiImporter> _wikiImporters =
464         new HashMap<String, WikiImporter>();
465 
466 }