com.erudika.scoold.controllers.QuestionsController.java Source code

Java tutorial

Introduction

Here is the source code for com.erudika.scoold.controllers.QuestionsController.java

Source

/*
 * Copyright 2013-2019 Erudika. https://erudika.com
 *
 * 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.
 *
 * For issues and patches go to: https://github.com/erudika
 */
package com.erudika.scoold.controllers;

import com.erudika.para.client.ParaClient;
import com.erudika.para.core.Address;
import com.erudika.para.utils.Config;
import com.erudika.para.utils.Pager;
import com.erudika.para.utils.Utils;
import com.erudika.scoold.core.Post;
import com.erudika.scoold.core.Profile;
import com.erudika.scoold.core.Question;
import com.erudika.scoold.utils.ScooldUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import static com.erudika.scoold.ScooldServer.SIGNINLINK;
import static com.erudika.scoold.ScooldServer.QUESTIONSLINK;
import static com.erudika.scoold.ScooldServer.SPACE_COOKIE;
import static com.erudika.scoold.utils.HttpUtils.getCookieValue;
import static com.erudika.scoold.utils.HttpUtils.setRawCookie;

/**
 *
 * @author Alex Bogdanovski [alex@erudika.com]
 */
@Controller
public class QuestionsController {

    private final ScooldUtils utils;
    private final ParaClient pc;

    @Inject
    public QuestionsController(ScooldUtils utils) {
        this.utils = utils;
        this.pc = utils.getParaClient();
    }

    @GetMapping({ "/", "/questions" })
    public String get(@RequestParam(required = false) String sortby, HttpServletRequest req, Model model) {
        if (!utils.isDefaultSpacePublic() && !utils.isAuthenticated(req)) {
            return "redirect:" + SIGNINLINK + "?returnto=" + QUESTIONSLINK;
        }
        getQuestions(sortby, null, req, model);
        model.addAttribute("path", "questions.vm");
        model.addAttribute("title", utils.getLang(req).get("questions.title"));
        model.addAttribute("questionsSelected", "navbtn-hover");
        return "base";
    }

    @GetMapping("/questions/tag/{tag}")
    public String getTagged(@PathVariable String tag, HttpServletRequest req, Model model) {
        Pager itemcount = utils.getPager("page", req);
        List<Question> questionslist = Collections.emptyList();
        String type = Utils.type(Question.class);
        String qf = utils.getSpaceFilteredQuery(req);
        if (!qf.isEmpty()) {
            if (qf.equals("*")) {
                questionslist = pc.findTagged(type, new String[] { tag }, itemcount);
            } else {
                questionslist = pc.findQuery(type, qf + " AND " + Config._TAGS + ":" + tag, itemcount);
            }
        }
        utils.fetchProfiles(questionslist);
        model.addAttribute("path", "questions.vm");
        model.addAttribute("title", utils.getLang(req).get("posts.tagged") + " - " + tag);
        model.addAttribute("questionsSelected", "navbtn-hover");
        model.addAttribute("tag", tag);
        model.addAttribute("itemcount", itemcount);
        model.addAttribute("questionslist", questionslist);
        return "base";
    }

    @GetMapping("/questions/similar/{like}")
    public void getSimilarAjax(@PathVariable String like, HttpServletRequest req, HttpServletResponse res)
            throws IOException {
        Profile authUser = utils.getAuthUser(req);
        StringBuilder sb = new StringBuilder();
        Question q = new Question();
        q.setTitle(like);
        q.setBody("");
        q.setTags(Arrays.asList(""));
        for (Post similarPost : utils.getSimilarPosts(q, new Pager(Config.getConfigInt("max_similar_posts", 7)))) {
            if (utils.isMod(authUser) || utils.canAccessSpace(authUser, similarPost.getSpace())) {
                boolean hasAnswer = !StringUtils.isBlank(similarPost.getAnswerid());
                sb.append("<span class=\"lightborder phm").append(hasAnswer ? " light-green white-text" : "")
                        .append("\">");
                sb.append(similarPost.getVotes());
                sb.append("</span> <a href=\"").append(similarPost.getPostLink(false, false)).append("\">");
                sb.append(similarPost.getTitle()).append("</a><br>");
            }
        }
        res.setCharacterEncoding("UTF-8");
        res.getWriter().print(sb.toString());
        res.setStatus(200);
    }

    @GetMapping("/questions/{filter}")
    public String getSorted(@PathVariable(required = false) String filter,
            @RequestParam(required = false) String sortby, HttpServletRequest req, Model model) {
        getQuestions(sortby, filter, req, model);
        model.addAttribute("path", "questions.vm");
        model.addAttribute("title", utils.getLang(req).get("questions.title"));
        model.addAttribute("questionsSelected", "navbtn-hover");
        return "base";
    }

    @GetMapping("/questions/ask")
    public String ask(HttpServletRequest req, Model model) {
        if (!utils.isAuthenticated(req)) {
            return "redirect:" + SIGNINLINK + "?returnto=" + QUESTIONSLINK + "/ask";
        }
        model.addAttribute("path", "questions.vm");
        model.addAttribute("askSelected", "navbtn-hover");
        model.addAttribute("includeGMapsScripts", utils.isNearMeFeatureEnabled());
        model.addAttribute("title",
                utils.getLang(req).get("questions.title") + " - " + utils.getLang(req).get("posts.ask"));
        return "base";
    }

    @PostMapping("/questions/ask")
    public String post(@RequestParam(required = false) String location,
            @RequestParam(required = false) String latlng, @RequestParam(required = false) String address,
            HttpServletRequest req, Model model) {
        if (utils.isAuthenticated(req)) {
            Profile authUser = utils.getAuthUser(req);
            String currentSpace = utils.getValidSpaceId(authUser, getCookieValue(req, SPACE_COOKIE));
            Question q = utils.populate(req, new Question(), "title", "body", "tags|,", "location");
            q.setCreatorid(authUser.getId());
            q.setSpace(currentSpace);
            Map<String, String> error = utils.validate(q);
            if (error.isEmpty()) {
                q.setLocation(location);
                String qid = q.create();
                if (!StringUtils.isBlank(latlng)) {
                    Address addr = new Address();
                    addr.setAddress(address);
                    addr.setCountry(location);
                    addr.setLatlng(latlng);
                    addr.setParentid(qid);
                    addr.setCreatorid(authUser.getId());
                    pc.create(addr);
                }
                authUser.setLastseen(System.currentTimeMillis());
            } else {
                model.addAttribute("error", error);
                model.addAttribute("path", "questions.vm");
                model.addAttribute("includeGMapsScripts", utils.isNearMeFeatureEnabled());
                model.addAttribute("askSelected", "navbtn-hover");
                return "base";
            }
            return "redirect:" + q.getPostLink(false, false);
        }
        return "redirect:" + SIGNINLINK + "?returnto=" + QUESTIONSLINK + "/ask";
    }

    @PostMapping({ "/questions/space/{space}", "/questions/space" })
    public String setSpace(@PathVariable(required = false) String space, HttpServletRequest req,
            HttpServletResponse res) {
        Profile authUser = utils.getAuthUser(req);
        if (authUser != null) {
            if (StringUtils.isBlank(space) || pc.read(utils.getSpaceId(space)) == null) {
                if (utils.canAccessSpace(authUser, space)) {
                    authUser.getSpaces().remove(space);
                    authUser.update();
                }
            }
            space = StringUtils.trimToEmpty(space);
            setRawCookie(SPACE_COOKIE, space, req, res, false, StringUtils.isBlank(space) ? 0 : 365 * 24 * 60 * 60);
        }
        res.setStatus(200);
        return "base";
    }

    private List<Question> getQuestions(String sortby, String filter, HttpServletRequest req, Model model) {
        Pager itemcount = utils.getPager("page", req);
        List<Question> questionslist = Collections.emptyList();
        String type = Utils.type(Question.class);
        Profile authUser = utils.getAuthUser(req);
        String currentSpace = utils.getValidSpaceId(authUser, getCookieValue(req, SPACE_COOKIE));
        boolean spaceFiltered = !StringUtils.isBlank(currentSpace);
        String query = getQuestionsQuery(authUser, sortby, currentSpace, itemcount);

        if (!StringUtils.isBlank(filter) && authUser != null) {
            if ("favtags".equals(filter)) {
                if (spaceFiltered) {
                    questionslist = pc.findQuery(type, getSpaceFilteredFavtagsQuery(currentSpace, authUser),
                            itemcount);
                } else {
                    questionslist = pc.findTermInList(type, Config._TAGS, authUser.getFavtags(), itemcount);
                }
            } else if ("local".equals(filter)) {
                String[] ll = authUser.getLatlng() == null ? new String[0] : authUser.getLatlng().split(",");
                if (ll.length == 2) {
                    double lat = NumberUtils.toDouble(ll[0]);
                    double lng = NumberUtils.toDouble(ll[1]);
                    questionslist = pc.findNearby(type, query, 25, lat, lng, itemcount);
                }
            }
            model.addAttribute("localFilterOn", "local".equals(filter));
            model.addAttribute("tagFilterOn", "favtags".equals(filter));
            model.addAttribute("filter", "/" + Utils.stripAndTrim(filter));
        } else {
            questionslist = pc.findQuery(type, query, itemcount);
        }

        utils.fetchProfiles(questionslist);
        model.addAttribute("itemcount", itemcount);
        model.addAttribute("questionslist", questionslist);
        return questionslist;
    }

    private String getSpaceFilteredFavtagsQuery(String currentSpace, Profile authUser) {
        if (utils.canAccessSpace(authUser, currentSpace)) {
            StringBuilder sb = new StringBuilder("properties.space:");
            sb.append(currentSpace).append(" AND (");
            for (int i = 0; i < authUser.getFavtags().size(); i++) {
                sb.append(Config._TAGS).append(":").append(authUser.getFavtags().get(i));
                if (i < authUser.getFavtags().size() - 1) {
                    sb.append(" OR ");
                }
            }
            sb.append(")");
            return sb.toString();
        }
        return "";
    }

    private String getQuestionsQuery(Profile authUser, String sortby, String currentSpace, Pager itemcount) {
        boolean spaceFiltered = !StringUtils.isBlank(currentSpace);
        String spaceFilter = "properties.space:\"" + currentSpace + "\"";
        String query = spaceFiltered ? spaceFilter : (utils.canAccessSpace(authUser, currentSpace) ? "*" : "");
        if ("activity".equals(sortby)) {
            itemcount.setSortby("updated");
        } else if ("votes".equals(sortby)) {
            itemcount.setSortby("votes");
        } else if ("unanswered".equals(sortby)) {
            itemcount.setSortby("timestamp");
            itemcount.setDesc(false);
            String q = "properties.answercount:0";
            query = spaceFiltered ? spaceFilter + " AND " + q
                    : (utils.canAccessSpace(authUser, currentSpace) ? q : "");
        } else if ("unapproved".equals(sortby)) {
            itemcount.setSortby("timestamp");
            itemcount.setDesc(false);
            String q = "properties.answercount:[1 TO *] NOT properties.answerid:[* TO *]";
            query = spaceFiltered ? spaceFilter + " AND " + q
                    : (utils.canAccessSpace(authUser, currentSpace) ? q : "");
        }
        return query;
    }
}