1   /**
2    * Copyright (c) 2000-2007 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.counter.service.CounterLocalServiceUtil;
26  import com.liferay.portal.PortalException;
27  import com.liferay.portal.SystemException;
28  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
29  import com.liferay.portal.kernel.util.ContentTypes;
30  import com.liferay.portal.kernel.util.Validator;
31  import com.liferay.portal.model.User;
32  import com.liferay.portal.model.impl.ResourceImpl;
33  import com.liferay.portal.service.ResourceLocalServiceUtil;
34  import com.liferay.portal.service.persistence.UserUtil;
35  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
36  import com.liferay.portlet.tags.service.TagsAssetLocalServiceUtil;
37  import com.liferay.portlet.wiki.NoSuchPageException;
38  import com.liferay.portlet.wiki.PageContentException;
39  import com.liferay.portlet.wiki.PageTitleException;
40  import com.liferay.portlet.wiki.model.WikiNode;
41  import com.liferay.portlet.wiki.model.WikiPage;
42  import com.liferay.portlet.wiki.model.impl.WikiPageImpl;
43  import com.liferay.portlet.wiki.service.WikiPageResourceLocalServiceUtil;
44  import com.liferay.portlet.wiki.service.base.WikiPageLocalServiceBaseImpl;
45  import com.liferay.portlet.wiki.service.persistence.WikiNodeUtil;
46  import com.liferay.portlet.wiki.service.persistence.WikiPageFinder;
47  import com.liferay.portlet.wiki.service.persistence.WikiPageUtil;
48  import com.liferay.portlet.wiki.util.Indexer;
49  import com.liferay.portlet.wiki.util.NodeFilter;
50  import com.liferay.portlet.wiki.util.WikiUtil;
51  import com.liferay.portlet.wiki.util.comparator.PageCreateDateComparator;
52  import com.liferay.util.MathUtil;
53  
54  import java.io.IOException;
55  
56  import java.util.ArrayList;
57  import java.util.Calendar;
58  import java.util.Collections;
59  import java.util.Date;
60  import java.util.HashSet;
61  import java.util.Iterator;
62  import java.util.List;
63  import java.util.Map;
64  import java.util.Set;
65  import java.util.regex.Matcher;
66  import java.util.regex.Pattern;
67  
68  import org.apache.commons.logging.Log;
69  import org.apache.commons.logging.LogFactory;
70  
71  /**
72   * <a href="WikiPageLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
73   *
74   * @author Brian Wing Shun Chan
75   *
76   */
77  public class WikiPageLocalServiceImpl extends WikiPageLocalServiceBaseImpl {
78  
79      public WikiPage addPage(long userId, long nodeId, String title)
80          throws PortalException, SystemException {
81  
82          // Page
83  
84          User user = UserUtil.findByPrimaryKey(userId);
85          Date now = new Date();
86  
87          validate(title);
88  
89          long pageId = CounterLocalServiceUtil.increment();
90  
91          long resourcePrimKey =
92              WikiPageResourceLocalServiceUtil.getPageResourcePrimKey(
93                  nodeId, title);
94  
95          WikiPage page = WikiPageUtil.create(pageId);
96  
97          page.setResourcePrimKey(resourcePrimKey);
98          page.setCompanyId(user.getCompanyId());
99          page.setUserId(user.getUserId());
100         page.setUserName(user.getFullName());
101         page.setCreateDate(now);
102         page.setNodeId(nodeId);
103         page.setTitle(title);
104         page.setVersion(WikiPageImpl.DEFAULT_VERSION);
105         page.setFormat(WikiPageImpl.DEFAULT_FORMAT);
106         page.setHead(true);
107 
108         WikiPageUtil.update(page);
109 
110         // Resources
111 
112         addPageResources(page.getNode(), page, true, true);
113 
114         return page;
115     }
116 
117     public void addPageResources(
118             long nodeId, String title, boolean addCommunityPermissions,
119             boolean addGuestPermissions)
120         throws PortalException, SystemException {
121 
122         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
123         WikiPage page = getPage(nodeId, title);
124 
125         addPageResources(
126             node, page, addCommunityPermissions, addGuestPermissions);
127     }
128 
129     public void addPageResources(
130             WikiNode node, WikiPage page, boolean addCommunityPermissions,
131             boolean addGuestPermissions)
132         throws PortalException, SystemException {
133 
134         ResourceLocalServiceUtil.addResources(
135             page.getCompanyId(), node.getGroupId(), page.getUserId(),
136             WikiPage.class.getName(), page.getResourcePrimKey(), false,
137             addCommunityPermissions, addGuestPermissions);
138     }
139 
140     public void addPageResources(
141             long nodeId, String title, String[] communityPermissions,
142             String[] guestPermissions)
143         throws PortalException, SystemException {
144 
145         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
146         WikiPage page = getPage(nodeId, title);
147 
148         addPageResources(node, page, communityPermissions, guestPermissions);
149     }
150 
151     public void addPageResources(
152             WikiNode node, WikiPage page, String[] communityPermissions,
153             String[] guestPermissions)
154         throws PortalException, SystemException {
155 
156         ResourceLocalServiceUtil.addModelResources(
157             page.getCompanyId(), node.getGroupId(), page.getUserId(),
158             WikiPage.class.getName(), page.getResourcePrimKey(),
159             communityPermissions, guestPermissions);
160     }
161 
162     public void deletePage(long nodeId, String title)
163         throws PortalException, SystemException {
164 
165         List pages = WikiPageUtil.findByN_T_H(nodeId, title, true, 0, 1);
166 
167         if (pages.size() > 0) {
168             WikiPage page = (WikiPage)pages.iterator().next();
169 
170             deletePage(page);
171         }
172     }
173 
174     public void deletePage(WikiPage page)
175         throws PortalException, SystemException {
176 
177         // Lucene
178 
179         try {
180             Indexer.deletePage(
181                 page.getCompanyId(), page.getNodeId(), page.getTitle());
182         }
183         catch (IOException ioe) {
184             _log.error("Deleting index " + page.getPrimaryKey(), ioe);
185         }
186 
187         // Tags
188 
189         TagsAssetLocalServiceUtil.deleteAsset(
190             WikiPage.class.getName(), page.getResourcePrimKey());
191 
192         // Message boards
193 
194         MBMessageLocalServiceUtil.deleteDiscussionMessages(
195             WikiPage.class.getName(), page.getResourcePrimKey());
196 
197         // Resources
198 
199         ResourceLocalServiceUtil.deleteResource(
200             page.getCompanyId(), WikiPage.class.getName(),
201             ResourceImpl.SCOPE_INDIVIDUAL, page.getResourcePrimKey());
202 
203         // Resource
204 
205         WikiPageResourceLocalServiceUtil.deletePageResource(
206             page.getNodeId(), page.getTitle());
207 
208         // All versions
209 
210         WikiPageUtil.removeByN_T(page.getNodeId(), page.getTitle());
211     }
212 
213     public void deletePages(long nodeId)
214         throws PortalException, SystemException {
215 
216         Iterator itr = WikiPageUtil.findByN_H(nodeId, true).iterator();
217 
218         while (itr.hasNext()) {
219             WikiPage page = (WikiPage)itr.next();
220 
221             deletePage(page);
222         }
223     }
224 
225     public List getLinks(long nodeId, String title) throws SystemException {
226         List links = new ArrayList();
227 
228         List pages = WikiPageUtil.findByN_H(nodeId, true);
229 
230         for (int i = 0; i < pages.size(); i++) {
231             WikiPage page = (WikiPage)pages.get(i);
232 
233             if (page.getFormat().equals(WikiPageImpl.CLASSIC_WIKI_FORMAT)) {
234                 NodeFilter filter = WikiUtil.getFilter(nodeId);
235 
236                 try {
237                     WikiUtil.convert(filter, page.getContent());
238 
239                     if (filter.getTitles().get(title) != null) {
240                         links.add(page);
241                     }
242                 }
243                 catch (IOException ioe) {
244                     ioe.printStackTrace();
245                 }
246             }
247         }
248 
249         Collections.sort(links);
250 
251         return links;
252     }
253 
254     public List getOrphans(long nodeId) throws SystemException {
255         List pageTitles = new ArrayList();
256 
257         List pages = WikiPageUtil.findByN_H(nodeId, true);
258 
259         for (int i = 0; i < pages.size(); i++) {
260             WikiPage page = (WikiPage)pages.get(i);
261 
262             if (page.getFormat().equals(WikiPageImpl.CLASSIC_WIKI_FORMAT)) {
263                 NodeFilter filter = WikiUtil.getFilter(nodeId);
264 
265                 try {
266                     WikiUtil.convert(filter, page.getContent());
267 
268                     pageTitles.add(filter.getTitles());
269                 }
270                 catch (IOException ioe) {
271                     ioe.printStackTrace();
272                 }
273             }
274         }
275 
276         Set notOrphans = new HashSet();
277 
278         for (int i = 0; i < pages.size(); i++) {
279             WikiPage page = (WikiPage)pages.get(i);
280 
281             for (int j = 0; j < pageTitles.size(); j++) {
282                 Map titles = (Map)pageTitles.get(j);
283 
284                 if (titles.get(page.getTitle()) != null) {
285                     notOrphans.add(page);
286 
287                     break;
288                 }
289             }
290         }
291 
292         List orphans = new ArrayList();
293 
294         for (int i = 0; i < pages.size(); i++) {
295             WikiPage page = (WikiPage)pages.get(i);
296 
297             if (!notOrphans.contains(page)) {
298                 orphans.add(page);
299             }
300         }
301 
302         Collections.sort(orphans);
303 
304         return orphans;
305     }
306 
307     public WikiPage getPage(long nodeId, String title)
308         throws PortalException, SystemException {
309 
310         List pages = WikiPageUtil.findByN_T_H(nodeId, title, true, 0, 1);
311 
312         if (pages.size() > 0) {
313             return (WikiPage)pages.iterator().next();
314         }
315         else {
316             throw new NoSuchPageException();
317         }
318     }
319 
320     public WikiPage getPage(long nodeId, String title, double version)
321         throws PortalException, SystemException {
322 
323         WikiPage page = null;
324 
325         if (version == 0) {
326             page = getPage(nodeId, title);
327         }
328         else {
329             page = WikiPageUtil.findByN_T_V(nodeId, title, version);
330         }
331 
332         return page;
333     }
334 
335     public List getPages(long nodeId, int begin, int end)
336         throws SystemException {
337 
338         return WikiPageUtil.findByNodeId(
339             nodeId, begin, end, new PageCreateDateComparator(false));
340     }
341 
342     public List getPages(long nodeId, String title, int begin, int end)
343         throws SystemException {
344 
345         return WikiPageUtil.findByN_T(
346             nodeId, title, begin, end, new PageCreateDateComparator(false));
347     }
348 
349     public List getPages(long nodeId, boolean head, int begin, int end)
350         throws SystemException {
351 
352         return WikiPageUtil.findByN_H(
353             nodeId, head, begin, end, new PageCreateDateComparator(false));
354     }
355 
356     public List getPages(
357             long nodeId, String title, boolean head, int begin, int end)
358         throws SystemException {
359 
360         return WikiPageUtil.findByN_T_H(
361             nodeId, title, head, begin, end,
362             new PageCreateDateComparator(false));
363     }
364 
365     public int getPagesCount(long nodeId) throws SystemException {
366         return WikiPageUtil.countByNodeId(nodeId);
367     }
368 
369     public int getPagesCount(long nodeId, String title)
370         throws SystemException {
371 
372         return WikiPageUtil.countByN_T(nodeId, title);
373     }
374 
375     public int getPagesCount(long nodeId, boolean head)
376         throws SystemException {
377 
378         return WikiPageUtil.countByN_H(nodeId, head);
379     }
380 
381     public int getPagesCount(long nodeId, String title, boolean head)
382         throws SystemException {
383 
384         return WikiPageUtil.countByN_T_H(nodeId, title, head);
385     }
386 
387     public List getRecentChanges(long nodeId, int begin, int end)
388         throws SystemException {
389 
390         Calendar cal = CalendarFactoryUtil.getCalendar();
391 
392         cal.add(Calendar.WEEK_OF_YEAR, -1);
393 
394         return WikiPageFinder.findByCreateDate(
395             nodeId, cal.getTime(), false, begin, end);
396     }
397 
398     public int getRecentChangesCount(long nodeId) throws SystemException {
399         Calendar cal = CalendarFactoryUtil.getCalendar();
400 
401         cal.add(Calendar.WEEK_OF_YEAR, -1);
402 
403         return WikiPageFinder.countByCreateDate(nodeId, cal.getTime(), false);
404     }
405 
406     public WikiPage revertPage(
407             long userId, long nodeId, String title, double version)
408         throws PortalException, SystemException {
409 
410         WikiPage oldPage = getPage(nodeId, title, version);
411 
412         return updatePage(
413             userId, nodeId, title, oldPage.getContent(), oldPage.getFormat(),
414             null);
415     }
416 
417     public WikiPage updatePage(
418             long userId, long nodeId, String title, String content,
419             String format, String[] tagsEntries)
420         throws PortalException, SystemException {
421 
422         // Page
423 
424         User user = UserUtil.findByPrimaryKey(userId);
425         Date now = new Date();
426 
427         validate(nodeId, content, format);
428 
429         WikiPage page = getPage(nodeId, title);
430 
431         long resourcePrimKey = page.getResourcePrimKey();
432 
433         page.setHead(false);
434 
435         WikiPageUtil.update(page);
436 
437         double oldVersion = page.getVersion();
438         double newVersion = MathUtil.format(oldVersion + 0.1, 1, 1);
439 
440         long pageId = CounterLocalServiceUtil.increment();
441 
442         page = WikiPageUtil.create(pageId);
443 
444         page.setResourcePrimKey(resourcePrimKey);
445         page.setCompanyId(user.getCompanyId());
446         page.setUserId(user.getUserId());
447         page.setUserName(user.getFullName());
448         page.setCreateDate(now);
449         page.setNodeId(nodeId);
450         page.setTitle(title);
451         page.setVersion(newVersion);
452         page.setContent(content);
453         page.setFormat(format);
454         page.setHead(true);
455 
456         WikiPageUtil.update(page);
457 
458         // Node
459 
460         WikiNode node = WikiNodeUtil.findByPrimaryKey(nodeId);
461 
462         node.setLastPostDate(now);
463 
464         WikiNodeUtil.update(node);
465 
466         // Tags
467 
468         updateAsset(page, tagsEntries);
469 
470         // Lucene
471 
472         try {
473             Indexer.updatePage(
474                 node.getCompanyId(), node.getGroupId(), nodeId, title, content);
475         }
476         catch (IOException ioe) {
477             _log.error("Indexing " + page.getPrimaryKey(), ioe);
478         }
479 
480         return page;
481     }
482 
483     protected void updateAsset(WikiPage page, String[] tagsEntries)
484         throws PortalException, SystemException {
485 
486         TagsAssetLocalServiceUtil.updateAsset(
487             page.getUserId(), WikiPage.class.getName(),
488             page.getResourcePrimKey(), tagsEntries, null, null, null, null,
489             ContentTypes.TEXT_HTML, page.getTitle(), page.getTitle(),
490             page.getTitle(), null, 0, 0);
491     }
492 
493     protected void validate(String title) throws PortalException {
494         if (Validator.isNull(title)) {
495             throw new PageTitleException();
496         }
497 
498         Pattern pattern = Pattern.compile("(((\\p{Lu}\\p{Ll}+)_?)+)");
499         Matcher matcher = pattern.matcher(title);
500 
501         if (!matcher.matches()) {
502             throw new PageTitleException();
503         }
504     }
505 
506     protected void validate(long nodeId, String content, String format)
507         throws PortalException {
508 
509         if (format.equals(WikiPageImpl.CLASSIC_WIKI_FORMAT)) {
510             try {
511                 NodeFilter filter = WikiUtil.getFilter(nodeId);
512 
513                 WikiUtil.convert(filter, content);
514             }
515             catch (Exception e) {
516                 throw new PageContentException();
517             }
518         }
519     }
520 
521     private static Log _log = LogFactory.getLog(WikiPageLocalServiceImpl.class);
522 
523 }