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