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.util.PortalUtil;
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   *
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.getScopeGroupId(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         // Indexer
203 
204         try {
205             Indexer.deletePages(node.getCompanyId(), node.getNodeId());
206         }
207         catch (SearchException se) {
208             _log.error("Deleting index " + node.getNodeId(), se);
209         }
210 
211         // Subscriptions
212 
213         subscriptionLocalService.deleteSubscriptions(
214             node.getCompanyId(), WikiNode.class.getName(), node.getNodeId());
215 
216         // Pages
217 
218         wikiPageLocalService.deletePages(node.getNodeId());
219 
220         // Resources
221 
222         resourceLocalService.deleteResource(
223             node.getCompanyId(), WikiNode.class.getName(),
224             ResourceConstants.SCOPE_INDIVIDUAL, node.getNodeId());
225 
226         // Node
227 
228         wikiNodePersistence.remove(node);
229     }
230 
231     public void deleteNodes(long groupId)
232         throws PortalException, SystemException {
233 
234         Iterator<WikiNode> itr = wikiNodePersistence.findByGroupId(
235             groupId).iterator();
236 
237         while (itr.hasNext()) {
238             WikiNode node = itr.next();
239 
240             deleteNode(node);
241         }
242     }
243 
244     public WikiNode getNode(long nodeId)
245         throws PortalException, SystemException {
246 
247         return wikiNodePersistence.findByPrimaryKey(nodeId);
248     }
249 
250     public WikiNode getNode(long groupId, String nodeName)
251         throws PortalException, SystemException {
252 
253         return wikiNodePersistence.findByG_N(groupId, nodeName);
254     }
255 
256     public List<WikiNode> getNodes(long groupId) throws SystemException {
257         return wikiNodePersistence.findByGroupId(groupId);
258     }
259 
260     public List<WikiNode> getNodes(long groupId, int start, int end)
261         throws SystemException {
262 
263         return wikiNodePersistence.findByGroupId(groupId, start, end);
264     }
265 
266     public int getNodesCount(long groupId) throws SystemException {
267         return wikiNodePersistence.countByGroupId(groupId);
268     }
269 
270     public void importPages(
271             long userId, long nodeId, String importer, File[] files,
272             Map<String, String[]> options)
273         throws PortalException, SystemException {
274 
275         WikiNode node = getNode(nodeId);
276 
277         getWikiImporter(importer).importPages(userId, node, files, options);
278     }
279 
280     public void reIndex(String[] ids) throws SystemException {
281         if (SearchEngineUtil.isIndexReadOnly()) {
282             return;
283         }
284 
285         long companyId = GetterUtil.getLong(ids[0]);
286 
287         try {
288             Iterator<WikiNode> nodesItr = wikiNodePersistence.findByCompanyId(
289                 companyId).iterator();
290 
291             while (nodesItr.hasNext()) {
292                 WikiNode node = nodesItr.next();
293 
294                 long nodeId = node.getNodeId();
295 
296                 Iterator<WikiPage> pagesItr = wikiPagePersistence.findByN_H(
297                     nodeId, true).iterator();
298 
299                 while (pagesItr.hasNext()) {
300                     WikiPage page = pagesItr.next();
301 
302                     long groupId = node.getGroupId();
303                     String title = page.getTitle();
304                     String content = page.getContent();
305                     Date modifiedDate = page.getModifiedDate();
306 
307                     String[] tagsEntries = tagsEntryLocalService.getEntryNames(
308                         WikiPage.class.getName(), page.getResourcePrimKey());
309 
310                     try {
311                         Indexer.updatePage(
312                             companyId, groupId, nodeId, title, content,
313                             modifiedDate, tagsEntries);
314                     }
315                     catch (SearchException se) {
316                         _log.error("Reindexing " + page.getPrimaryKey(), se);
317                     }
318                 }
319             }
320         }
321         catch (SystemException se) {
322             throw se;
323         }
324         catch (Exception e) {
325             throw new SystemException(e);
326         }
327     }
328 
329     public Hits search(
330             long companyId, long groupId, long[] nodeIds, String keywords,
331             int start, int end)
332         throws SystemException {
333 
334         try {
335             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
336 
337             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
338 
339             if (groupId > 0) {
340                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
341             }
342 
343             if ((nodeIds != null) && (nodeIds.length > 0)) {
344                 BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create();
345 
346                 for (long nodeId : nodeIds) {
347                     TermQuery termQuery = TermQueryFactoryUtil.create(
348                         Field.ENTRY_CLASS_PK, nodeId);
349 
350                     nodeIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
351                 }
352 
353                 contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
354             }
355 
356             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
357 
358             if (Validator.isNotNull(keywords)) {
359                 searchQuery.addTerm(Field.TITLE, keywords);
360                 searchQuery.addTerm(Field.CONTENT, keywords);
361                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
362             }
363 
364             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
365 
366             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
367 
368             if (searchQuery.clauses().size() > 0) {
369                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
370             }
371 
372             return SearchEngineUtil.search(companyId, fullQuery, start, end);
373         }
374         catch (Exception e) {
375             throw new SystemException(e);
376         }
377     }
378 
379     public void subscribeNode(long userId, long nodeId)
380         throws PortalException, SystemException {
381 
382         subscriptionLocalService.addSubscription(
383             userId, WikiNode.class.getName(), nodeId);
384     }
385 
386     public void unsubscribeNode(long userId, long nodeId)
387         throws PortalException, SystemException {
388 
389         subscriptionLocalService.deleteSubscription(
390             userId, WikiNode.class.getName(), nodeId);
391     }
392 
393     public WikiNode updateNode(long nodeId, String name, String description)
394         throws PortalException, SystemException {
395 
396         WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
397 
398         validate(nodeId, node.getGroupId(), name);
399 
400         node.setModifiedDate(new Date());
401         node.setName(name);
402         node.setDescription(description);
403 
404         wikiNodePersistence.update(node, false);
405 
406         return node;
407     }
408 
409     protected WikiImporter getWikiImporter(String importer)
410         throws SystemException {
411 
412         WikiImporter wikiImporter = _wikiImporters.get(importer);
413 
414         if (wikiImporter == null) {
415             String importerClass = PropsUtil.get(
416                 PropsKeys.WIKI_IMPORTERS_CLASS, new Filter(importer));
417 
418             if (importerClass != null) {
419                 wikiImporter = (WikiImporter)InstancePool.get(importerClass);
420 
421                 _wikiImporters.put(importer, wikiImporter);
422             }
423 
424             if (importer == null) {
425                 throw new SystemException(
426                     "Unable to instantiate wiki importer class " +
427                         importerClass);
428             }
429         }
430 
431         return wikiImporter;
432     }
433 
434     protected void validate(long groupId, String name)
435         throws PortalException, SystemException {
436 
437         validate(0, groupId, name);
438     }
439 
440     protected void validate(long nodeId, long groupId, String name)
441         throws PortalException, SystemException {
442 
443         if (name.equalsIgnoreCase("tag")) {
444             throw new NodeNameException(name + " is reserved");
445         }
446 
447         if (!Validator.isName(name)) {
448             throw new NodeNameException();
449         }
450 
451         WikiNode node = wikiNodePersistence.fetchByG_N(groupId, name);
452 
453         if ((node != null) && (node.getNodeId() != nodeId)) {
454             throw new DuplicateNodeNameException();
455         }
456     }
457 
458     private static Log _log =
459          LogFactoryUtil.getLog(WikiNodeLocalServiceImpl.class);
460 
461     private Map<String, WikiImporter> _wikiImporters =
462         new HashMap<String, WikiImporter>();
463 
464 }