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