csns.web.controller.WikiController.java Source code

Java tutorial

Introduction

Here is the source code for csns.web.controller.WikiController.java

Source

/*
 * This file is part of the CSNetwork Services (CSNS) project.
 * 
 * Copyright 2012, Chengyu Sun (csun@calstatela.edu).
 * 
 * CSNS is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 * 
 * CSNS is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with CSNS. If not, see http://www.gnu.org/licenses/agpl.html.
 */
package csns.web.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.outerj.daisy.diff.HtmlCleaner;
import org.outerj.daisy.diff.XslFilter;
import org.outerj.daisy.diff.html.HTMLDiffer;
import org.outerj.daisy.diff.html.HtmlSaxDiffOutput;
import org.outerj.daisy.diff.html.TextNodeComparator;
import org.outerj.daisy.diff.html.dom.DomTreeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.HandlerMapping;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import csns.model.core.Subscription;
import csns.model.core.User;
import csns.model.core.dao.SubscriptionDao;
import csns.model.wiki.Page;
import csns.model.wiki.Revision;
import csns.model.wiki.dao.PageDao;
import csns.model.wiki.dao.RevisionDao;
import csns.security.SecurityUtils;
import csns.util.NotificationService;

@Controller
public class WikiController {

    @Autowired
    private PageDao pageDao;

    @Autowired
    private RevisionDao revisionDao;

    @Autowired
    private SubscriptionDao subscriptionDao;

    @Autowired
    private NotificationService notificationService;

    private static final Logger logger = LoggerFactory.getLogger(WikiController.class);

    public static String getDept(String path) {
        String prefix = "/wiki/content/department/";

        if (!path.startsWith(prefix))
            return null;

        int beginIndex = prefix.length();
        int endIndex = path.indexOf('/', beginIndex);
        return endIndex > 0 ? path.substring(beginIndex, endIndex) : null;
    }

    // @RequestMapping("/department/{dept}/wiki/content/**")
    @RequestMapping("/wiki/content/**")
    public String view(@RequestParam(required = false) Long revisionId, HttpServletRequest request,
            ModelMap models) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        models.put("path", path);

        Revision revision = revisionId == null ? revisionDao.getRevision(path)
                : revisionDao.getRevision(revisionId);
        if (revision == null)
            return "wiki/nopage";

        if (StringUtils.hasText(revision.getPage().getPassword())
                && request.getSession().getAttribute(path) == null)
            return "wiki/password";

        revision.getPage().incrementViews();
        pageDao.savePage(revision.getPage());
        models.put("revision", revision);

        String dept = getDept(path);
        if (revision.isIncludeSidebar()) {
            String sidebar = dept == null ? "/wiki/content/sidebar"
                    : "/wiki/content/department/" + dept + "/sidebar";
            models.put("sidebar", revisionDao.getRevision(sidebar));
        }

        if (SecurityUtils.isAuthenticated()) {
            User user = SecurityUtils.getUser();
            models.put("user", user);
            models.put("isAdmin", dept == null ? user.isSysadmin() : user.isAdmin(dept));

            Subscription subscription = subscriptionDao.getSubscription(revision.getPage(), user);
            if (subscription != null) {
                if (subscription.isNotificationSent()) {
                    subscription.setNotificationSent(false);
                    subscription = subscriptionDao.saveSubscription(subscription);
                }
                models.put("subscription", subscription);
            }
        }

        return "wiki/page";
    }

    @RequestMapping(value = "/wiki/password", method = RequestMethod.POST)
    public String password(@RequestParam String path, @RequestParam String password, HttpSession session) {
        if (pageDao.getPage(path).getPassword().equals(password))
            session.setAttribute(path, "password verifeid");

        return "redirect:" + path;
    }

    @RequestMapping(value = "/wiki/move", method = RequestMethod.GET)
    public String move(@RequestParam String from, ModelMap models) {
        Page page = pageDao.getPage(from);
        User user = SecurityUtils.getUser();
        String dept = getDept(from);
        if (!page.getOwner().getId().equals(user.getId())
                && (dept == null ? !user.isSysadmin() : user.isAdmin(dept))) {
            models.put("message", "error.wiki.not.owner");
            return "error";
        }

        return "wiki/move";
    }

    @RequestMapping(value = "/wiki/move", method = RequestMethod.POST)
    public String move(@RequestParam String from, @RequestParam String to, ModelMap models) {
        if (pageDao.getPage(to) != null) {
            models.put("message", "error.wiki.page.exists");
            return "error";
        }

        Page page = pageDao.getPage(from);
        page.setPath(to);
        page = pageDao.savePage(page);

        User user = SecurityUtils.getUser();
        logger.info("Wiki page " + from + " moved to " + to + " by " + user.getUsername());

        subscriptionDao.subscribe(page, user);

        String subject = "Wiki Page " + from + " Moved";
        String vTemplate = "notification.wiki.page.moved.vm";
        Map<String, Object> vModels = new HashMap<String, Object>();
        vModels.put("page", page);
        vModels.put("author", user);
        vModels.put("from", from);
        notificationService.notifiy(page, subject, vTemplate, vModels, false);

        return "redirect:" + to;
    }

    @RequestMapping("/wiki/revisions")
    public String revisions(@RequestParam Long id, ModelMap models) {
        Page page = pageDao.getPage(id);
        models.put("page", page);
        models.put("revisions", revisionDao.getRevisions(page));
        return "wiki/revisions";
    }

    @RequestMapping("/wiki/revert")
    public String revert(@RequestParam Long revisionId, HttpSession session, ModelMap models) {
        Revision revision = revisionDao.getRevision(revisionId);
        Page page = revision.getPage();
        User user = SecurityUtils.getUser();
        String dept = getDept(page.getPath());
        if (page.isLocked() && !page.getOwner().getId().equals(user.getId())
                && (dept == null ? !user.isSysadmin() : !user.isAdmin(dept))) {
            models.put("message", "error.wiki.not.owner");
            return "error";
        }

        revision = revision.clone();
        revision.setAuthor(user);
        revision.setDate(new Date());
        revision = revisionDao.saveRevision(revision);

        subscriptionDao.subscribe(page, user);

        String subject = "New Revision of Wiki Page " + page.getPath();
        String vTemplate = "notification.new.wiki.revision.vm";
        Map<String, Object> vModels = new HashMap<String, Object>();
        vModels.put("page", page);
        vModels.put("author", user);
        notificationService.notifiy(page, subject, vTemplate, vModels, true);

        return "redirect:" + page.getPath();
    }

    @RequestMapping("/wiki/compare")
    public String compare(@RequestParam("revisionId") Long[] ids, ModelMap models) throws Exception {
        Long oldId = ids[0] < ids[1] ? ids[0] : ids[1];
        Long newId = ids[0] > ids[1] ? ids[0] : ids[1];
        Revision oldRevision = revisionDao.getRevision(oldId);
        Revision newRevision = revisionDao.getRevision(newId);

        models.put("path", newRevision.getPage().getPath());
        models.put("diffResult", diff(oldRevision, newRevision));
        return "wiki/compare";
    }

    @RequestMapping("/wiki/discussions")
    public String discussions(@RequestParam Long id, ModelMap models) {
        models.put("page", pageDao.getPage(id));
        return "wiki/discussions";
    }

    @RequestMapping("/wiki/search")
    public String search(@RequestParam String term, ModelMap models) {
        models.put("results", pageDao.searchPages(term, 40));
        return "wiki/search";
    }

    private String diff(Revision oldRevision, Revision newRevision) throws Exception {
        StringWriter result = new StringWriter();
        TransformerHandler transformerHandler = ((SAXTransformerFactory) TransformerFactory.newInstance())
                .newTransformerHandler();
        transformerHandler.setResult(new StreamResult(result));
        XslFilter xslFilter = new XslFilter();
        ContentHandler contentHandler = xslFilter.xsl(transformerHandler, "xsl/diff2html.xsl");

        contentHandler.startDocument();
        HtmlSaxDiffOutput diffOutput = new HtmlSaxDiffOutput(contentHandler, "diff");
        HTMLDiffer differ = new HTMLDiffer(diffOutput);
        TextNodeComparator leftComparator = createComparator(oldRevision);
        TextNodeComparator rightComparator = createComparator(newRevision);
        differ.diff(leftComparator, rightComparator);
        contentHandler.endDocument();

        return result.toString();
    }

    private TextNodeComparator createComparator(Revision revision) throws IOException, SAXException {
        Locale locale = Locale.getDefault();
        HtmlCleaner cleaner = new HtmlCleaner();
        DomTreeBuilder domTreeBuilder = new DomTreeBuilder();

        InputSource inputSource = new InputSource(
                new ByteArrayInputStream(revision.getContent().getBytes("UTF-8")));
        cleaner.cleanAndParse(inputSource, domTreeBuilder);

        return new TextNodeComparator(domTreeBuilder, locale);
    }

}