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