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