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