src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java

Sat, 05 Dec 2020 13:05:00 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 05 Dec 2020 13:05:00 +0100
changeset 162
2adc8623dd89
parent 161
3d9218457b62
child 167
3f30adba1c63
permissions
-rw-r--r--

enables markdown support in issue descriptions and comments - fixes #10

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2018 Mike Becker. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  *
    28  */
    29 package de.uapcore.lightpit.modules;
    32 import de.uapcore.lightpit.*;
    33 import de.uapcore.lightpit.dao.DaoProvider;
    34 import de.uapcore.lightpit.entities.*;
    35 import de.uapcore.lightpit.types.WebColor;
    36 import de.uapcore.lightpit.viewmodel.*;
    37 import de.uapcore.lightpit.viewmodel.util.IssueSorter;
    38 import org.slf4j.Logger;
    39 import org.slf4j.LoggerFactory;
    41 import javax.servlet.ServletException;
    42 import javax.servlet.annotation.WebServlet;
    43 import javax.servlet.http.HttpServletRequest;
    44 import javax.servlet.http.HttpServletResponse;
    45 import java.io.IOException;
    46 import java.sql.Date;
    47 import java.sql.SQLException;
    48 import java.util.List;
    49 import java.util.NoSuchElementException;
    50 import java.util.Optional;
    51 import java.util.stream.Collectors;
    52 import java.util.stream.Stream;
    54 @WebServlet(
    55         name = "ProjectsModule",
    56         urlPatterns = "/projects/*"
    57 )
    58 public final class ProjectsModule extends AbstractLightPITServlet {
    60     private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
    62     @Override
    63     protected String getResourceBundleName() {
    64         return "localization.projects";
    65     }
    67     private static int parseIntOrZero(String str) {
    68         try {
    69             return Integer.parseInt(str);
    70         } catch (NumberFormatException ex) {
    71             return 0;
    72         }
    73     }
    75     private void populate(ProjectView viewModel, PathParameters pathParameters, DaoProvider dao) {
    76         final var projectDao = dao.getProjectDao();
    77         final var versionDao = dao.getVersionDao();
    78         final var componentDao = dao.getComponentDao();
    80         projectDao.list().stream().map(ProjectInfo::new).forEach(viewModel.getProjectList()::add);
    82         if (pathParameters == null)
    83             return;
    85         // Select Project
    86         final var project = projectDao.findByNode(pathParameters.get("project"));
    87         if (project == null)
    88             return;
    90         final var info = new ProjectInfo(project);
    91         info.setVersions(versionDao.list(project));
    92         info.setComponents(componentDao.list(project));
    93         info.setIssueSummary(projectDao.getIssueSummary(project));
    94         viewModel.setProjectInfo(info);
    96         // Select Version
    97         final var versionNode = pathParameters.get("version");
    98         if (versionNode != null) {
    99             if ("no-version".equals(versionNode)) {
   100                 viewModel.setVersionFilter(ProjectView.NO_VERSION);
   101             } else if ("all-versions".equals(versionNode)) {
   102                 viewModel.setVersionFilter(ProjectView.ALL_VERSIONS);
   103             } else {
   104                 viewModel.setVersionFilter(versionDao.findByNode(project, versionNode));
   105             }
   106         }
   108         // Select Component
   109         final var componentNode = pathParameters.get("component");
   110         if (componentNode != null) {
   111             if ("no-component".equals(componentNode)) {
   112                 viewModel.setComponentFilter(ProjectView.NO_COMPONENT);
   113             } else if ("all-components".equals(componentNode)) {
   114                 viewModel.setComponentFilter(ProjectView.ALL_COMPONENTS);
   115             } else {
   116                 viewModel.setComponentFilter(componentDao.findByNode(project, componentNode));
   117             }
   118         }
   119     }
   121     private static String sanitizeNode(String node, String defaultValue) {
   122         String result = node == null || node.isBlank() ? defaultValue : node;
   123         result = result.replace('/', '-');
   124         if (result.equals(".") || result.equals("..")) {
   125             return "_"+result;
   126         } else {
   127             return result;
   128         }
   129     }
   131     private void forwardView(HttpServletRequest req, HttpServletResponse resp, ProjectView viewModel, String name) throws ServletException, IOException {
   132         setViewModel(req, viewModel);
   133         setContentPage(req, name);
   134         setStylesheet(req, "projects");
   135         setNavigationMenu(req, "project-navmenu");
   136         renderSite(req, resp);
   137     }
   139     @RequestMapping(method = HttpMethod.GET)
   140     public void index(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws SQLException, ServletException, IOException {
   141         final var viewModel = new ProjectView();
   142         populate(viewModel, null, dao);
   144         final var projectDao = dao.getProjectDao();
   145         final var versionDao = dao.getVersionDao();
   147         for (var info : viewModel.getProjectList()) {
   148             info.setVersions(versionDao.list(info.getProject()));
   149             info.setIssueSummary(projectDao.getIssueSummary(info.getProject()));
   150         }
   152         forwardView(req, resp, viewModel, "projects");
   153     }
   155     private void configureProjectEditor(ProjectEditView viewModel, Project project, DaoProvider dao) throws SQLException {
   156         viewModel.setProject(project);
   157         viewModel.setUsers(dao.getUserDao().list());
   158     }
   160     @RequestMapping(requestPath = "$project/edit", method = HttpMethod.GET)
   161     public void edit(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DaoProvider dao) throws IOException, SQLException, ServletException {
   162         final var viewModel = new ProjectEditView();
   163         populate(viewModel, pathParams, dao);
   165         if (!viewModel.isProjectInfoPresent()) {
   166             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   167             return;
   168         }
   170         configureProjectEditor(viewModel, viewModel.getProjectInfo().getProject(), dao);
   171         forwardView(req, resp, viewModel, "project-form");
   172     }
   174     @RequestMapping(requestPath = "create", method = HttpMethod.GET)
   175     public void create(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws SQLException, ServletException, IOException {
   176         final var viewModel = new ProjectEditView();
   177         populate(viewModel, null, dao);
   178         configureProjectEditor(viewModel, new Project(-1), dao);
   179         forwardView(req, resp, viewModel, "project-form");
   180     }
   182     @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
   183     public void commit(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   185         try {
   186             final var project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
   187             project.setName(getParameter(req, String.class, "name").orElseThrow());
   189             final var node = getParameter(req, String.class, "node").orElse(null);
   190             project.setNode(sanitizeNode(node, project.getName()));
   192             getParameter(req, String.class, "description").ifPresent(project::setDescription);
   193             getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
   194             getParameter(req, Integer.class, "owner").map(
   195                     ownerId -> ownerId >= 0 ? new User(ownerId) : null
   196             ).ifPresent(project::setOwner);
   198             final var projectDao = dao.getProjectDao();
   199             if (project.getId() > 0) {
   200                 // TODO: unused return value
   201                 projectDao.update(project);
   202             } else {
   203                 projectDao.save(project);
   204             }
   206             setRedirectLocation(req, "./projects/");
   207             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   208             LOG.debug("Successfully updated project {}", project.getName());
   210             renderSite(req, resp);
   211         } catch (NoSuchElementException | IllegalArgumentException ex) {
   212             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   213             // TODO: implement - fix issue #21
   214         }
   215     }
   217     @RequestMapping(requestPath = "$project/$component/$version/issues/", method = HttpMethod.GET)
   218     public void issues(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DaoProvider dao) throws SQLException, IOException, ServletException {
   219         final var viewModel = new ProjectDetailsView();
   220         populate(viewModel, pathParams, dao);
   222         if (!viewModel.isEveryFilterValid()) {
   223             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   224             return;
   225         }
   227         final var project = viewModel.getProjectInfo().getProject();
   228         final var version = viewModel.getVersionFilter();
   229         final var component = viewModel.getComponentFilter();
   231         final var issueDao = dao.getIssueDao();
   233         final List<Issue> issues;
   234         if (version.equals(ProjectView.NO_VERSION)) {
   235             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   236                 issues = issueDao.list(project, (Version) null);
   237             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   238                 issues = issueDao.list(project, null, null);
   239             } else {
   240                 issues = issueDao.list(project, component, null);
   241             }
   242         } else if (version.equals(ProjectView.ALL_VERSIONS)) {
   243             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   244                 issues = issueDao.list(project);
   245             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   246                 issues = issueDao.list(project, (Component)null);
   247             } else {
   248                 issues = issueDao.list(project, component);
   249             }
   250         } else {
   251             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   252                 issues = issueDao.list(project, version);
   253             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   254                 issues = issueDao.list(project, null, version);
   255             } else {
   256                 issues = issueDao.list(project, component, version);
   257             }
   258         }
   260         for (var issue : issues) issueDao.joinVersionInformation(issue);
   261         issues.sort(new IssueSorter(
   262                 new IssueSorter.Criteria(IssueSorter.Field.DONE, true),
   263                 new IssueSorter.Criteria(IssueSorter.Field.ETA, true),
   264                 new IssueSorter.Criteria(IssueSorter.Field.UPDATED, false)
   265         ));
   268         viewModel.getProjectDetails().updateDetails(issues);
   269         if (version.getId() > 0)
   270             viewModel.getProjectDetails().updateVersionInfo(version);
   272         forwardView(req, resp, viewModel, "project-details");
   273     }
   275     @RequestMapping(requestPath = "$project/versions/", method = HttpMethod.GET)
   276     public void versions(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   277         final var viewModel = new VersionsView();
   278         populate(viewModel, pathParameters, dao);
   280         final var projectInfo = viewModel.getProjectInfo();
   281         if (projectInfo == null) {
   282             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   283             return;
   284         }
   286         final var issueDao = dao.getIssueDao();
   287         final var issues = issueDao.list(projectInfo.getProject());
   288         for (var issue : issues) issueDao.joinVersionInformation(issue);
   289         viewModel.update(projectInfo.getVersions(), issues);
   291         forwardView(req, resp, viewModel, "versions");
   292     }
   294     @RequestMapping(requestPath = "$project/versions/$version/edit", method = HttpMethod.GET)
   295     public void editVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   296         final var viewModel = new VersionEditView();
   297         populate(viewModel, pathParameters, dao);
   299         if (viewModel.getProjectInfo() == null || viewModel.getVersionFilter() == null) {
   300             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   301             return;
   302         }
   304         viewModel.setVersion(viewModel.getVersionFilter());
   306         forwardView(req, resp, viewModel, "version-form");
   307     }
   309     @RequestMapping(requestPath = "$project/create-version", method = HttpMethod.GET)
   310     public void createVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   311         final var viewModel = new VersionEditView();
   312         populate(viewModel, pathParameters, dao);
   314         if (viewModel.getProjectInfo() == null) {
   315             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   316             return;
   317         }
   319         viewModel.setVersion(new Version(-1));
   321         forwardView(req, resp, viewModel, "version-form");
   322     }
   324     @RequestMapping(requestPath = "commit-version", method = HttpMethod.POST)
   325     public void commitVersion(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   327         try {
   328             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   329             if (project == null) {
   330                 // TODO: improve error handling, because not found is not correct for this POST request
   331                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   332                 return;
   333             }
   334             final var version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
   335             version.setName(getParameter(req, String.class, "name").orElseThrow());
   337             final var node = getParameter(req, String.class, "node").orElse(null);
   338             version.setNode(sanitizeNode(node, version.getName()));
   340             getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
   341             version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
   343             final var versionDao = dao.getVersionDao();
   344             if (version.getId() > 0) {
   345                 // TODO: use return value
   346                 versionDao.update(version);
   347             } else {
   348                 versionDao.save(version, project);
   349             }
   351             setRedirectLocation(req, "./projects/" + project.getNode() + "/versions/");
   352             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   354             renderSite(req, resp);
   355         } catch (NoSuchElementException | IllegalArgumentException ex) {
   356             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   357             // TODO: implement - fix issue #21
   358         }
   359     }
   361     @RequestMapping(requestPath = "$project/components/", method = HttpMethod.GET)
   362     public void components(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   363         final var viewModel = new ComponentsView();
   364         populate(viewModel, pathParameters, dao);
   366         final var projectInfo = viewModel.getProjectInfo();
   367         if (projectInfo == null) {
   368             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   369             return;
   370         }
   372         final var issueDao = dao.getIssueDao();
   373         final var issues = issueDao.list(projectInfo.getProject());
   374         viewModel.update(projectInfo.getComponents(), issues);
   376         forwardView(req, resp, viewModel, "components");
   377     }
   379     @RequestMapping(requestPath = "$project/components/$component/edit", method = HttpMethod.GET)
   380     public void editComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   381         final var viewModel = new ComponentEditView();
   382         populate(viewModel, pathParameters, dao);
   384         if (viewModel.getProjectInfo() == null || viewModel.getComponentFilter() == null) {
   385             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   386             return;
   387         }
   389         viewModel.setComponent(viewModel.getComponentFilter());
   390         viewModel.setUsers(dao.getUserDao().list());
   392         forwardView(req, resp, viewModel, "component-form");
   393     }
   395     @RequestMapping(requestPath = "$project/create-component", method = HttpMethod.GET)
   396     public void createComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   397         final var viewModel = new ComponentEditView();
   398         populate(viewModel, pathParameters, dao);
   400         if (viewModel.getProjectInfo() == null) {
   401             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   402             return;
   403         }
   405         viewModel.setComponent(new Component(-1));
   406         viewModel.setUsers(dao.getUserDao().list());
   408         forwardView(req, resp, viewModel, "component-form");
   409     }
   411     @RequestMapping(requestPath = "commit-component", method = HttpMethod.POST)
   412     public void commitComponent(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   414         try {
   415             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   416             if (project == null) {
   417                 // TODO: improve error handling, because not found is not correct for this POST request
   418                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   419                 return;
   420             }
   421             final var component = new Component(getParameter(req, Integer.class, "id").orElseThrow());
   422             component.setName(getParameter(req, String.class, "name").orElseThrow());
   424             final var node = getParameter(req, String.class, "node").orElse(null);
   425             component.setNode(sanitizeNode(node, component.getName()));
   427             component.setColor(getParameter(req, WebColor.class, "color").orElseThrow());
   428             getParameter(req, Integer.class, "ordinal").ifPresent(component::setOrdinal);
   429             getParameter(req, Integer.class, "lead").map(
   430                     userid -> userid >= 0 ? new User(userid) : null
   431             ).ifPresent(component::setLead);
   432             getParameter(req, String.class, "description").ifPresent(component::setDescription);
   434             final var componentDao = dao.getComponentDao();
   435             if (component.getId() > 0) {
   436                 // TODO: use return value
   437                 componentDao.update(component);
   438             } else {
   439                 componentDao.save(component, project);
   440             }
   442             setRedirectLocation(req, "./projects/" + project.getNode() + "/components/");
   443             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   445             renderSite(req, resp);
   446         } catch (NoSuchElementException | IllegalArgumentException ex) {
   447             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   448             // TODO: implement - fix issue #21
   449         }
   450     }
   452     private void configureIssueEditor(IssueEditView viewModel, Issue issue, DaoProvider dao) throws SQLException {
   453         final var project = viewModel.getProjectInfo().getProject();
   454         issue.setProject(project); // automatically set current project for new issues
   455         viewModel.setIssue(issue);
   456         viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions());
   457         viewModel.setUsers(dao.getUserDao().list());
   458         viewModel.setComponents(dao.getComponentDao().list(project));
   459     }
   461     @RequestMapping(requestPath = "$project/issues/$issue/view", method = HttpMethod.GET)
   462     public void viewIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   463         final var viewModel = new IssueDetailView();
   464         populate(viewModel, pathParameters, dao);
   466         final var projectInfo = viewModel.getProjectInfo();
   467         if (projectInfo == null) {
   468             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   469             return;
   470         }
   472         final var issueDao = dao.getIssueDao();
   473         final var issue = issueDao.find(parseIntOrZero(pathParameters.get("issue")));
   474         if (issue == null) {
   475             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   476             return;
   477         }
   479         issueDao.joinVersionInformation(issue);
   480         viewModel.setIssue(issue);
   481         viewModel.setComments(issueDao.listComments(issue));
   483         viewModel.processMarkdown();
   485         forwardView(req, resp, viewModel, "issue-view");
   486     }
   488     // TODO: why should the issue editor be child of $project?
   489     @RequestMapping(requestPath = "$project/issues/$issue/edit", method = HttpMethod.GET)
   490     public void editIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   491         final var viewModel = new IssueEditView();
   492         populate(viewModel, pathParameters, dao);
   494         final var projectInfo = viewModel.getProjectInfo();
   495         if (projectInfo == null) {
   496             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   497             return;
   498         }
   500         final var issueDao = dao.getIssueDao();
   501         final var issue = issueDao.find(parseIntOrZero(pathParameters.get("issue")));
   502         if (issue == null) {
   503             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   504             return;
   505         }
   507         issueDao.joinVersionInformation(issue);
   508         configureIssueEditor(viewModel, issue, dao);
   510         forwardView(req, resp, viewModel, "issue-form");
   511     }
   513     @RequestMapping(requestPath = "$project/create-issue", method = HttpMethod.GET)
   514     public void createIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   515         final var viewModel = new IssueEditView();
   516         populate(viewModel, pathParameters, dao);
   518         final var projectInfo = viewModel.getProjectInfo();
   519         if (projectInfo == null) {
   520             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   521             return;
   522         }
   524         final var issue = new Issue(-1);
   525         issue.setProject(projectInfo.getProject());
   526         configureIssueEditor(viewModel, issue, dao);
   528         forwardView(req, resp, viewModel, "issue-form");
   529     }
   531     @RequestMapping(requestPath = "commit-issue", method = HttpMethod.POST)
   532     public void commitIssue(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   533         try {
   534             final var issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
   535             final var componentId = getParameter(req, Integer.class, "component");
   536             final Component component;
   537             if (componentId.isPresent()) {
   538                 component = dao.getComponentDao().find(componentId.get());
   539             } else {
   540                 component = null;
   541             }
   542             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   543             if (project == null) {
   544                 // TODO: improve error handling, because not found is not correct for this POST request
   545                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   546                 return;
   547             }
   548             issue.setProject(project);
   549             getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
   550             getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
   551             issue.setSubject(getParameter(req, String.class, "subject").orElseThrow());
   552             issue.setComponent(component);
   553             getParameter(req, Integer.class, "assignee").map(userid -> {
   554                 if (userid >= 0) {
   555                     return new User(userid);
   556                 } else if (userid == -2) {
   557                     return Optional.ofNullable(component).map(Component::getLead).orElse(null);
   558                 } else {
   559                     return null;
   560                 }
   561             }
   562             ).ifPresent(issue::setAssignee);
   563             getParameter(req, String.class, "description").ifPresent(issue::setDescription);
   564             getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
   566             getParameter(req, Integer[].class, "affected")
   567                     .map(Stream::of)
   568                     .map(stream ->
   569                             stream.map(Version::new).collect(Collectors.toList())
   570                     ).ifPresent(issue::setAffectedVersions);
   571             getParameter(req, Integer[].class, "resolved")
   572                     .map(Stream::of)
   573                     .map(stream ->
   574                             stream.map(Version::new).collect(Collectors.toList())
   575                     ).ifPresent(issue::setResolvedVersions);
   577             final var issueDao = dao.getIssueDao();
   578             if (issue.getId() > 0) {
   579                 // TODO: use return value
   580                 issueDao.update(issue);
   581             } else {
   582                 issueDao.save(issue, project);
   583             }
   585             // TODO: fix redirect location
   586             setRedirectLocation(req, "./projects/" + issue.getProject().getNode()+"/issues/"+issue.getId()+"/view");
   587             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   589             renderSite(req, resp);
   590         } catch (NoSuchElementException | IllegalArgumentException ex) {
   591             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   592             // TODO: implement - fix issue #21
   593         }
   594     }
   596     @RequestMapping(requestPath = "commit-issue-comment", method = HttpMethod.POST)
   597     public void commentIssue(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   598         final var issueIdParam = getParameter(req, Integer.class, "issueid");
   599         if (issueIdParam.isEmpty()) {
   600             resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Detected manipulated form.");
   601             return;
   602         }
   603         final var issue = dao.getIssueDao().find(issueIdParam.get());
   604         if (issue == null) {
   605             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   606             return;
   607         }
   608         try {
   609             final var issueComment = new IssueComment(getParameter(req, Integer.class, "commentid").orElse(-1));
   610             issueComment.setComment(getParameter(req, String.class, "comment").orElse(""));
   612             if (issueComment.getComment().isBlank()) {
   613                 throw new IllegalArgumentException("comment.null");
   614             }
   616             LOG.debug("User {} is commenting on issue #{}", req.getRemoteUser(), issue.getId());
   617             if (req.getRemoteUser() != null) {
   618                 Optional.ofNullable(dao.getUserDao().findByUsername(req.getRemoteUser())).ifPresent(issueComment::setAuthor);
   619             }
   621             dao.getIssueDao().saveComment(issue, issueComment);
   623             // TODO: fix redirect location
   624             setRedirectLocation(req, "./projects/" + issue.getProject().getNode()+"/issues/"+issue.getId()+"/view");
   625             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   627             renderSite(req, resp);
   628         } catch (NoSuchElementException | IllegalArgumentException ex) {
   629             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   630             // TODO: implement - fix issue #21
   631         }
   632     }
   633 }

mercurial