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

Thu, 19 Nov 2020 13:58:54 +0100

author
mike@uapl01.localdomain
date
Thu, 19 Nov 2020 13:58:54 +0100
changeset 159
86b5d8a1662f
parent 158
4f912cd42876
child 161
3d9218457b62
permissions
-rw-r--r--

migrates DAO classes

     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) throws SQLException {
    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 ("no-version".equals(versionNode)) {
    99             viewModel.setVersionFilter(ProjectView.NO_VERSION);
   100         } else if ("all-versions".equals(versionNode) || versionNode == null) {
   101             viewModel.setVersionFilter(ProjectView.ALL_VERSIONS);
   102         } else {
   103             viewModel.setVersionFilter(versionDao.findByNode(project, versionNode));
   104         }
   106         // Select Component
   107         final var componentNode = pathParameters.get("component");
   108         if ("no-component".equals(componentNode)) {
   109             viewModel.setComponentFilter(ProjectView.NO_COMPONENT);
   110         } else if ("all-components".equals(componentNode) || componentNode == null) {
   111             viewModel.setComponentFilter(ProjectView.ALL_COMPONENTS);
   112         } else {
   113             viewModel.setComponentFilter(componentDao.findByNode(project, componentNode));
   114         }
   115     }
   117     private static String sanitizeNode(String node, String defaultValue) {
   118         String result = node == null || node.isBlank() ? defaultValue : node;
   119         result = result.replace('/', '-');
   120         if (result.equals(".") || result.equals("..")) {
   121             return "_"+result;
   122         } else {
   123             return result;
   124         }
   125     }
   127     private void forwardView(HttpServletRequest req, HttpServletResponse resp, ProjectView viewModel, String name) throws ServletException, IOException {
   128         setViewModel(req, viewModel);
   129         setContentPage(req, name);
   130         setStylesheet(req, "projects");
   131         setNavigationMenu(req, "project-navmenu");
   132         renderSite(req, resp);
   133     }
   135     @RequestMapping(method = HttpMethod.GET)
   136     public void index(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws SQLException, ServletException, IOException {
   137         final var viewModel = new ProjectView();
   138         populate(viewModel, null, dao);
   140         final var projectDao = dao.getProjectDao();
   141         final var versionDao = dao.getVersionDao();
   143         for (var info : viewModel.getProjectList()) {
   144             info.setVersions(versionDao.list(info.getProject()));
   145             info.setIssueSummary(projectDao.getIssueSummary(info.getProject()));
   146         }
   148         forwardView(req, resp, viewModel, "projects");
   149     }
   151     private void configureProjectEditor(ProjectEditView viewModel, Project project, DaoProvider dao) throws SQLException {
   152         viewModel.setProject(project);
   153         viewModel.setUsers(dao.getUserDao().list());
   154     }
   156     @RequestMapping(requestPath = "$project/edit", method = HttpMethod.GET)
   157     public void edit(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DaoProvider dao) throws IOException, SQLException, ServletException {
   158         final var viewModel = new ProjectEditView();
   159         populate(viewModel, pathParams, dao);
   161         if (!viewModel.isProjectInfoPresent()) {
   162             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   163             return;
   164         }
   166         configureProjectEditor(viewModel, viewModel.getProjectInfo().getProject(), dao);
   167         forwardView(req, resp, viewModel, "project-form");
   168     }
   170     @RequestMapping(requestPath = "create", method = HttpMethod.GET)
   171     public void create(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws SQLException, ServletException, IOException {
   172         final var viewModel = new ProjectEditView();
   173         populate(viewModel, null, dao);
   174         configureProjectEditor(viewModel, new Project(-1), dao);
   175         forwardView(req, resp, viewModel, "project-form");
   176     }
   178     @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
   179     public void commit(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   181         try {
   182             final var project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
   183             project.setName(getParameter(req, String.class, "name").orElseThrow());
   185             final var node = getParameter(req, String.class, "node").orElse(null);
   186             project.setNode(sanitizeNode(node, project.getName()));
   188             getParameter(req, String.class, "description").ifPresent(project::setDescription);
   189             getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
   190             getParameter(req, Integer.class, "owner").map(
   191                     ownerId -> ownerId >= 0 ? new User(ownerId) : null
   192             ).ifPresent(project::setOwner);
   194             final var projectDao = dao.getProjectDao();
   195             if (project.getId() > 0) {
   196                 // TODO: unused return value
   197                 projectDao.update(project);
   198             } else {
   199                 projectDao.save(project);
   200             }
   202             setRedirectLocation(req, "./projects/");
   203             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   204             LOG.debug("Successfully updated project {}", project.getName());
   206             renderSite(req, resp);
   207         } catch (NoSuchElementException | IllegalArgumentException ex) {
   208             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   209             // TODO: implement - fix issue #21
   210         }
   211     }
   213     @RequestMapping(requestPath = "$project/$component/$version/issues/", method = HttpMethod.GET)
   214     public void issues(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DaoProvider dao) throws SQLException, IOException, ServletException {
   215         final var viewModel = new ProjectDetailsView();
   216         populate(viewModel, pathParams, dao);
   218         if (!viewModel.isEveryFilterValid()) {
   219             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   220             return;
   221         }
   223         final var project = viewModel.getProjectInfo().getProject();
   224         final var version = viewModel.getVersionFilter();
   225         final var component = viewModel.getComponentFilter();
   227         final var issueDao = dao.getIssueDao();
   229         final List<Issue> issues;
   230         if (version.equals(ProjectView.NO_VERSION)) {
   231             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   232                 issues = issueDao.list(project, (Version) null);
   233             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   234                 issues = issueDao.list(project, null, null);
   235             } else {
   236                 issues = issueDao.list(project, component, null);
   237             }
   238         } else if (version.equals(ProjectView.ALL_VERSIONS)) {
   239             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   240                 issues = issueDao.list(project);
   241             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   242                 issues = issueDao.list(project, (Component)null);
   243             } else {
   244                 issues = issueDao.list(project, component);
   245             }
   246         } else {
   247             if (component.equals(ProjectView.ALL_COMPONENTS)) {
   248                 issues = issueDao.list(project, version);
   249             } else if (component.equals(ProjectView.NO_COMPONENT)) {
   250                 issues = issueDao.list(project, null, version);
   251             } else {
   252                 issues = issueDao.list(project, component, version);
   253             }
   254         }
   256         for (var issue : issues) issueDao.joinVersionInformation(issue);
   257         issues.sort(new IssueSorter(
   258                 new IssueSorter.Criteria(IssueSorter.Field.DONE, true),
   259                 new IssueSorter.Criteria(IssueSorter.Field.ETA, true),
   260                 new IssueSorter.Criteria(IssueSorter.Field.UPDATED, false)
   261         ));
   264         viewModel.getProjectDetails().updateDetails(issues);
   265         if (version.getId() > 0)
   266             viewModel.getProjectDetails().updateVersionInfo(version);
   268         forwardView(req, resp, viewModel, "project-details");
   269     }
   271     @RequestMapping(requestPath = "$project/versions/", method = HttpMethod.GET)
   272     public void versions(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   273         final var viewModel = new VersionsView();
   274         populate(viewModel, pathParameters, dao);
   276         final var projectInfo = viewModel.getProjectInfo();
   277         if (projectInfo == null) {
   278             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   279             return;
   280         }
   282         final var issueDao = dao.getIssueDao();
   283         final var issues = issueDao.list(projectInfo.getProject());
   284         for (var issue : issues) issueDao.joinVersionInformation(issue);
   285         viewModel.update(projectInfo.getVersions(), issues);
   287         forwardView(req, resp, viewModel, "versions");
   288     }
   290     @RequestMapping(requestPath = "$project/versions/$version/edit", method = HttpMethod.GET)
   291     public void editVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   292         final var viewModel = new VersionEditView();
   293         populate(viewModel, pathParameters, dao);
   295         if (viewModel.getProjectInfo() == null || viewModel.getVersionFilter() == null) {
   296             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   297             return;
   298         }
   300         viewModel.setVersion(viewModel.getVersionFilter());
   302         forwardView(req, resp, viewModel, "version-form");
   303     }
   305     @RequestMapping(requestPath = "$project/create-version", method = HttpMethod.GET)
   306     public void createVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   307         final var viewModel = new VersionEditView();
   308         populate(viewModel, pathParameters, dao);
   310         if (viewModel.getProjectInfo() == null) {
   311             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   312             return;
   313         }
   315         viewModel.setVersion(new Version(-1));
   317         forwardView(req, resp, viewModel, "version-form");
   318     }
   320     @RequestMapping(requestPath = "commit-version", method = HttpMethod.POST)
   321     public void commitVersion(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   323         try {
   324             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   325             if (project == null) {
   326                 // TODO: improve error handling, because not found is not correct for this POST request
   327                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   328                 return;
   329             }
   330             final var version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
   331             version.setName(getParameter(req, String.class, "name").orElseThrow());
   333             final var node = getParameter(req, String.class, "node").orElse(null);
   334             version.setNode(sanitizeNode(node, version.getName()));
   336             getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
   337             version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
   339             final var versionDao = dao.getVersionDao();
   340             if (version.getId() > 0) {
   341                 // TODO: use return value
   342                 versionDao.update(version);
   343             } else {
   344                 versionDao.save(version, project);
   345             }
   347             setRedirectLocation(req, "./projects/" + project.getNode() + "/versions/");
   348             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   350             renderSite(req, resp);
   351         } catch (NoSuchElementException | IllegalArgumentException ex) {
   352             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   353             // TODO: implement - fix issue #21
   354         }
   355     }
   357     @RequestMapping(requestPath = "$project/components/", method = HttpMethod.GET)
   358     public void components(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   359         final var viewModel = new ComponentsView();
   360         populate(viewModel, pathParameters, dao);
   362         final var projectInfo = viewModel.getProjectInfo();
   363         if (projectInfo == null) {
   364             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   365             return;
   366         }
   368         final var issueDao = dao.getIssueDao();
   369         final var issues = issueDao.list(projectInfo.getProject());
   370         viewModel.update(projectInfo.getComponents(), issues);
   372         forwardView(req, resp, viewModel, "components");
   373     }
   375     @RequestMapping(requestPath = "$project/components/$component/edit", method = HttpMethod.GET)
   376     public void editComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   377         final var viewModel = new ComponentEditView();
   378         populate(viewModel, pathParameters, dao);
   380         if (viewModel.getProjectInfo() == null || viewModel.getComponentFilter() == null) {
   381             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   382             return;
   383         }
   385         viewModel.setComponent(viewModel.getComponentFilter());
   386         viewModel.setUsers(dao.getUserDao().list());
   388         forwardView(req, resp, viewModel, "component-form");
   389     }
   391     @RequestMapping(requestPath = "$project/create-component", method = HttpMethod.GET)
   392     public void createComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   393         final var viewModel = new ComponentEditView();
   394         populate(viewModel, pathParameters, dao);
   396         if (viewModel.getProjectInfo() == null) {
   397             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   398             return;
   399         }
   401         viewModel.setComponent(new Component(-1));
   402         viewModel.setUsers(dao.getUserDao().list());
   404         forwardView(req, resp, viewModel, "component-form");
   405     }
   407     @RequestMapping(requestPath = "commit-component", method = HttpMethod.POST)
   408     public void commitComponent(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   410         try {
   411             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   412             if (project == null) {
   413                 // TODO: improve error handling, because not found is not correct for this POST request
   414                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   415                 return;
   416             }
   417             final var component = new Component(getParameter(req, Integer.class, "id").orElseThrow());
   418             component.setName(getParameter(req, String.class, "name").orElseThrow());
   420             final var node = getParameter(req, String.class, "node").orElse(null);
   421             component.setNode(sanitizeNode(node, component.getName()));
   423             component.setColor(getParameter(req, WebColor.class, "color").orElseThrow());
   424             getParameter(req, Integer.class, "ordinal").ifPresent(component::setOrdinal);
   425             getParameter(req, Integer.class, "lead").map(
   426                     userid -> userid >= 0 ? new User(userid) : null
   427             ).ifPresent(component::setLead);
   428             getParameter(req, String.class, "description").ifPresent(component::setDescription);
   430             final var componentDao = dao.getComponentDao();
   431             if (component.getId() > 0) {
   432                 // TODO: use return value
   433                 componentDao.update(component);
   434             } else {
   435                 componentDao.save(component, project);
   436             }
   438             setRedirectLocation(req, "./projects/" + project.getNode() + "/components/");
   439             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   441             renderSite(req, resp);
   442         } catch (NoSuchElementException | IllegalArgumentException ex) {
   443             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   444             // TODO: implement - fix issue #21
   445         }
   446     }
   448     private void configureIssueEditor(IssueEditView viewModel, Issue issue, DaoProvider dao) throws SQLException {
   449         final var project = viewModel.getProjectInfo().getProject();
   450         issue.setProject(project); // automatically set current project for new issues
   451         viewModel.setIssue(issue);
   452         viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions());
   453         viewModel.setUsers(dao.getUserDao().list());
   454         viewModel.setComponents(dao.getComponentDao().list(project));
   455     }
   457     @RequestMapping(requestPath = "$project/issues/$issue/view", method = HttpMethod.GET)
   458     public void viewIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   459         final var viewModel = new IssueDetailView();
   460         populate(viewModel, pathParameters, dao);
   462         final var projectInfo = viewModel.getProjectInfo();
   463         if (projectInfo == null) {
   464             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   465             return;
   466         }
   468         final var issueDao = dao.getIssueDao();
   469         final var issue = issueDao.find(parseIntOrZero(pathParameters.get("issue")));
   470         if (issue == null) {
   471             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   472             return;
   473         }
   475         issueDao.joinVersionInformation(issue);
   476         viewModel.setIssue(issue);
   477         viewModel.setComments(issueDao.listComments(issue));
   479         forwardView(req, resp, viewModel, "issue-view");
   480     }
   482     // TODO: why should the issue editor be child of $project?
   483     @RequestMapping(requestPath = "$project/issues/$issue/edit", method = HttpMethod.GET)
   484     public void editIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   485         final var viewModel = new IssueEditView();
   486         populate(viewModel, pathParameters, dao);
   488         final var projectInfo = viewModel.getProjectInfo();
   489         if (projectInfo == null) {
   490             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   491             return;
   492         }
   494         final var issueDao = dao.getIssueDao();
   495         final var issue = issueDao.find(parseIntOrZero(pathParameters.get("issue")));
   496         if (issue == null) {
   497             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   498             return;
   499         }
   501         issueDao.joinVersionInformation(issue);
   502         configureIssueEditor(viewModel, issue, dao);
   504         forwardView(req, resp, viewModel, "issue-form");
   505     }
   507     @RequestMapping(requestPath = "$project/create-issue", method = HttpMethod.GET)
   508     public void createIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DaoProvider dao) throws IOException, SQLException, ServletException {
   509         final var viewModel = new IssueEditView();
   510         populate(viewModel, pathParameters, dao);
   512         final var projectInfo = viewModel.getProjectInfo();
   513         if (projectInfo == null) {
   514             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   515             return;
   516         }
   518         final var issue = new Issue(-1);
   519         issue.setProject(projectInfo.getProject());
   520         configureIssueEditor(viewModel, issue, dao);
   522         forwardView(req, resp, viewModel, "issue-form");
   523     }
   525     @RequestMapping(requestPath = "commit-issue", method = HttpMethod.POST)
   526     public void commitIssue(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   527         try {
   528             final var issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
   529             final var componentId = getParameter(req, Integer.class, "component");
   530             final Component component;
   531             if (componentId.isPresent()) {
   532                 component = dao.getComponentDao().find(componentId.get());
   533             } else {
   534                 component = null;
   535             }
   536             final var project = dao.getProjectDao().find(getParameter(req, Integer.class, "pid").orElseThrow());
   537             if (project == null) {
   538                 // TODO: improve error handling, because not found is not correct for this POST request
   539                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   540                 return;
   541             }
   542             issue.setProject(project);
   543             getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
   544             getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
   545             issue.setSubject(getParameter(req, String.class, "subject").orElseThrow());
   546             issue.setComponent(component);
   547             getParameter(req, Integer.class, "assignee").map(userid -> {
   548                 if (userid >= 0) {
   549                     return new User(userid);
   550                 } else if (userid == -2) {
   551                     return Optional.ofNullable(component).map(Component::getLead).orElse(null);
   552                 } else {
   553                     return null;
   554                 }
   555             }
   556             ).ifPresent(issue::setAssignee);
   557             getParameter(req, String.class, "description").ifPresent(issue::setDescription);
   558             getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
   560             getParameter(req, Integer[].class, "affected")
   561                     .map(Stream::of)
   562                     .map(stream ->
   563                             stream.map(Version::new).collect(Collectors.toList())
   564                     ).ifPresent(issue::setAffectedVersions);
   565             getParameter(req, Integer[].class, "resolved")
   566                     .map(Stream::of)
   567                     .map(stream ->
   568                             stream.map(Version::new).collect(Collectors.toList())
   569                     ).ifPresent(issue::setResolvedVersions);
   571             final var issueDao = dao.getIssueDao();
   572             if (issue.getId() > 0) {
   573                 // TODO: use return value
   574                 issueDao.update(issue);
   575             } else {
   576                 issueDao.save(issue, project);
   577             }
   579             // TODO: fix redirect location
   580             setRedirectLocation(req, "./projects/" + issue.getProject().getNode()+"/issues/"+issue.getId()+"/view");
   581             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   583             renderSite(req, resp);
   584         } catch (NoSuchElementException | IllegalArgumentException ex) {
   585             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   586             // TODO: implement - fix issue #21
   587         }
   588     }
   590     @RequestMapping(requestPath = "commit-issue-comment", method = HttpMethod.POST)
   591     public void commentIssue(HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException, ServletException {
   592         final var issueIdParam = getParameter(req, Integer.class, "issueid");
   593         if (issueIdParam.isEmpty()) {
   594             resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Detected manipulated form.");
   595             return;
   596         }
   597         final var issue = dao.getIssueDao().find(issueIdParam.get());
   598         if (issue == null) {
   599             resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   600             return;
   601         }
   602         try {
   603             final var issueComment = new IssueComment(getParameter(req, Integer.class, "commentid").orElse(-1));
   604             issueComment.setComment(getParameter(req, String.class, "comment").orElse(""));
   606             if (issueComment.getComment().isBlank()) {
   607                 throw new IllegalArgumentException("comment.null");
   608             }
   610             LOG.debug("User {} is commenting on issue #{}", req.getRemoteUser(), issue.getId());
   611             if (req.getRemoteUser() != null) {
   612                 Optional.ofNullable(dao.getUserDao().findByUsername(req.getRemoteUser())).ifPresent(issueComment::setAuthor);
   613             }
   615             dao.getIssueDao().saveComment(issue, issueComment);
   617             // TODO: fix redirect location
   618             setRedirectLocation(req, "./projects/" + issue.getProject().getNode()+"/issues/"+issue.getId()+"/view");
   619             setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   621             renderSite(req, resp);
   622         } catch (NoSuchElementException | IllegalArgumentException ex) {
   623             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   624             // TODO: implement - fix issue #21
   625         }
   626     }
   627 }

mercurial