ru.org.linux.group.GroupController.java Source code

Java tutorial

Introduction

Here is the source code for ru.org.linux.group.GroupController.java

Source

/*
 * Copyright 1998-2012 Linux.org.ru
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package ru.org.linux.group;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import ru.org.linux.auth.AccessViolationException;
import ru.org.linux.section.Section;
import ru.org.linux.section.SectionService;
import ru.org.linux.site.Template;
import ru.org.linux.spring.Configuration;
import ru.org.linux.topic.TopicTagService;
import ru.org.linux.user.IgnoreListDao;
import ru.org.linux.user.User;
import ru.org.linux.user.UserDao;
import ru.org.linux.user.UserNotFoundException;
import ru.org.linux.util.BadImageException;
import ru.org.linux.util.ImageInfo;
import ru.org.linux.util.ServletParameterBadValueException;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.util.*;

@Controller
public class GroupController {
    public static final int MAX_OFFSET = 300;

    @Autowired
    private GroupDao groupDao;

    @Autowired
    private SectionService sectionService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private GroupInfoPrepareService prepareService;

    @Autowired
    private IgnoreListDao ignoreListDao;

    @Autowired
    private GroupPermissionService groupPermissionService;

    @Autowired
    private TopicTagService topicTagService;

    @Autowired
    private Configuration configuration;

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void setDataSource(DataSource ds) {
        jdbcTemplate = new JdbcTemplate(ds);
    }

    @RequestMapping("/group.jsp")
    public ModelAndView topics(@RequestParam("group") int groupId,
            @RequestParam(value = "offset", required = false) Integer offsetObject) throws Exception {
        Group group = groupDao.getGroup(groupId);

        if (offsetObject != null) {
            return new ModelAndView(new RedirectView(group.getUrl() + "?offset=" + offsetObject.toString()));
        } else {
            return new ModelAndView(new RedirectView(group.getUrl()));
        }
    }

    @RequestMapping("/group-lastmod.jsp")
    public ModelAndView topicsLastmod(@RequestParam("group") int groupId,
            @RequestParam(value = "offset", required = false) Integer offsetObject) throws Exception {
        Group group = groupDao.getGroup(groupId);

        if (offsetObject != null) {
            return new ModelAndView(
                    new RedirectView(group.getUrl() + "?offset=" + offsetObject.toString() + "&lastmod=true"));
        } else {
            return new ModelAndView(new RedirectView(group.getUrl() + "?lastmod=true"));
        }
    }

    @RequestMapping("/forum/{group}/{year:\\d+}/{month:\\d+}")
    public ModelAndView forumArchive(@PathVariable("group") String groupName,
            @RequestParam(defaultValue = "0", value = "offset") int offset, @PathVariable int year,
            @PathVariable int month, HttpServletRequest request, HttpServletResponse response) throws Exception {
        return forum(groupName, offset, false, request, response, year, month);
    }

    @RequestMapping("/forum/{group}")
    public ModelAndView forum(@PathVariable("group") String groupName,
            @RequestParam(defaultValue = "0", value = "offset") int offset,
            @RequestParam(defaultValue = "false") boolean lastmod, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        return forum(groupName, offset, lastmod, request, response, null, null);
    }

    private List<TopicsListItem> getStickyTopics(Group group, int messagesInPage) {
        String q = "SELECT topics.title as subj, lastmod, userid, topics.id as msgid, deleted, topics.stat1, topics.stat3, topics.stat4, topics.sticky, topics.resolved "
                + "FROM topics WHERE sticky AND NOT deleted AND topics.groupid=? ORDER BY msgid DESC";

        SqlRowSet rs = jdbcTemplate.queryForRowSet(q, group.getId());

        return prepareTopic(rs, messagesInPage);
    }

    // TODO: move to dao/service
    private List<TopicsListItem> getTopics(Group group, int messagesInPage, boolean lastmod, Integer year,
            Integer month, int topics, int offset, boolean showDeleted, boolean showIgnored,
            @Nullable User currentUser) {
        Set<Integer> ignoreList;

        if (currentUser != null) {
            ignoreList = ignoreListDao.get(currentUser);
        } else {
            ignoreList = Collections.emptySet();
        }

        String delq = showDeleted ? "" : " AND NOT deleted ";

        String q = "SELECT topics.title as subj, lastmod, userid, topics.id as msgid, deleted, topics.stat1, topics.stat3, topics.stat4, topics.sticky, topics.resolved "
                + "FROM topics WHERE NOT sticky AND topics.groupid=" + group.getId() + delq;

        if (year != null) {
            q += " AND postdate>='" + year + '-' + month + "-01'::timestamp AND (postdate<'" + year + '-' + month
                    + "-01'::timestamp+'1 month'::interval)";
        }

        String ignq = "";

        if (!showIgnored && currentUser != null) {
            int currentUserId = currentUser.getId();
            if (!ignoreList.isEmpty()) {
                ignq = " AND topics.userid NOT IN (SELECT ignored FROM ignore_list WHERE userid=" + currentUserId
                        + ')';
            }

            if (!currentUser.isModerator()) {
                ignq += " AND topics.id NOT IN (select distinct tags.msgid from tags, user_tags "
                        + "where tags.tagid=user_tags.tag_id and user_tags.is_favorite = false and user_id="
                        + currentUserId + ") ";
            }
        }

        SqlRowSet rs;

        if (!lastmod) {
            if (year == null) {
                if (offset == 0) {
                    q += " AND postdate>CURRENT_TIMESTAMP-'3 month'::interval ";
                }

                rs = jdbcTemplate
                        .queryForRowSet(q + ignq + " ORDER BY msgid DESC LIMIT " + topics + " OFFSET " + offset);
            } else {
                rs = jdbcTemplate
                        .queryForRowSet(q + ignq + " ORDER BY msgid DESC LIMIT " + topics + " OFFSET " + offset);
            }
        } else {
            rs = jdbcTemplate
                    .queryForRowSet(q + ignq + " ORDER BY lastmod DESC LIMIT " + topics + " OFFSET " + offset);
        }

        return prepareTopic(rs, messagesInPage);
    }

    private List<TopicsListItem> prepareTopic(SqlRowSet rs, int messagesInPage) {
        List<TopicsListItem> topicsList = new ArrayList<>();

        while (rs.next()) {
            User author;

            try {
                author = userDao.getUserCached(rs.getInt("userid"));
            } catch (UserNotFoundException e) {
                throw new RuntimeException(e);
            }

            ImmutableList<String> tags = topicTagService.getMessageTagsForTitle(rs.getInt("msgid"));

            TopicsListItem topic = new TopicsListItem(author, rs, messagesInPage, tags);

            topicsList.add(topic);
        }

        return topicsList;
    }

    private ModelAndView forum(@PathVariable("group") String groupName,
            @RequestParam(defaultValue = "0", value = "offset") int offset,
            @RequestParam(defaultValue = "false") boolean lastmod, HttpServletRequest request,
            HttpServletResponse response, Integer year, Integer month) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Template tmpl = Template.getTemplate(request);

        boolean showDeleted = request.getParameter("deleted") != null;
        params.put("showDeleted", showDeleted);

        Section section = sectionService.getSection(Section.SECTION_FORUM);
        params.put("groupList", groupDao.getGroups(section));

        Group group = groupDao.getGroup(section, groupName);

        if (showDeleted && !"POST".equals(request.getMethod())) {
            return new ModelAndView(new RedirectView(group.getUrl()));
        }

        if (showDeleted && !tmpl.isSessionAuthorized()) {
            throw new AccessViolationException("  ");
        }

        boolean firstPage;

        if (offset != 0) {
            firstPage = false;

            if (offset < 0) {
                throw new ServletParameterBadValueException("offset",
                        "offset    ");
            }

            if (year == null && offset > MAX_OFFSET) {
                return new ModelAndView(new RedirectView(group.getUrl() + "archive"));
            }
        } else {
            firstPage = true;
        }

        params.put("firstPage", firstPage);
        params.put("offset", offset);
        params.put("prevPage", offset - tmpl.getProf().getTopics());
        params.put("nextPage", offset + tmpl.getProf().getTopics());
        params.put("lastmod", lastmod);

        boolean showIgnored = false;
        if (request.getParameter("showignored") != null) {
            showIgnored = "t".equals(request.getParameter("showignored"));
        }

        params.put("showIgnored", showIgnored);

        params.put("group", group);

        if (group.getImage() != null) {
            try {
                params.put("groupImagePath", '/' + tmpl.getStyle() + group.getImage());
                ImageInfo info = new ImageInfo(
                        configuration.getHTMLPathPrefix() + tmpl.getStyle() + group.getImage());
                params.put("groupImageInfo", info);
            } catch (BadImageException ex) {
                params.put("groupImagePath", null);
                params.put("groupImageInfo", null);
            }
        } else {
            params.put("groupImagePath", null);
            params.put("groupImageInfo", null);
        }

        params.put("section", section);

        params.put("groupInfo", prepareService.prepareGroupInfo(group, request.isSecure()));

        if (year != null) {
            if (year < 1990 || year > 3000) {
                throw new ServletParameterBadValueException("year", "  ");
            }

            if (month < 1 || month > 12) {
                throw new ServletParameterBadValueException("month",
                        "  ??");
            }

            params.put("year", year);
            params.put("month", month);
            params.put("url", group.getUrl() + year + '/' + month + '/');
        } else {
            params.put("url", group.getUrl());
        }

        List<TopicsListItem> mainTopics = getTopics(group, tmpl.getProf().getMessages(), lastmod, year, month,
                tmpl.getProf().getTopics(), offset, showDeleted, showIgnored, tmpl.getCurrentUser());

        if (year == null && offset == 0 && !lastmod) {
            List<TopicsListItem> stickyTopics = getStickyTopics(group, tmpl.getProf().getMessages());

            params.put("topicsList", Lists.newArrayList(Iterables.concat(stickyTopics, mainTopics)));
        } else {
            params.put("topicsList", mainTopics);
        }

        if (year != null) {
            params.put("hasNext",
                    offset + tmpl.getProf().getTopics() < getArchiveCount(group.getId(), year, month));
        } else {
            params.put("hasNext", offset < MAX_OFFSET && mainTopics.size() == tmpl.getProf().getTopics());
        }

        params.put("addable", groupPermissionService.isTopicPostingAllowed(group, tmpl.getCurrentUser()));

        response.setDateHeader("Expires", System.currentTimeMillis() + 90 * 1000);

        return new ModelAndView("group", params);
    }

    private int getArchiveCount(int groupid, int year, int month) {
        List<Integer> res = jdbcTemplate.queryForList(
                "SELECT c FROM monthly_stats WHERE groupid=? AND year=? AND month=?", Integer.class, groupid, year,
                month);

        if (!res.isEmpty()) {
            return res.get(0);
        } else {
            return 0;
        }
    }

    @ExceptionHandler(GroupNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ModelAndView handleNotFoundException() {
        return new ModelAndView("errors/code404");
    }
}