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