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

Thu, 08 Oct 2020 20:16:47 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 08 Oct 2020 20:16:47 +0200
changeset 109
2e0669e814ff
parent 107
b5f740a87af4
child 110
9d0be0b1580f
permissions
-rw-r--r--

adds versions overview

includes major refactoring of side menu generation

universe@41 1 /*
universe@41 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@41 3 *
universe@41 4 * Copyright 2018 Mike Becker. All rights reserved.
universe@41 5 *
universe@41 6 * Redistribution and use in source and binary forms, with or without
universe@41 7 * modification, are permitted provided that the following conditions are met:
universe@41 8 *
universe@41 9 * 1. Redistributions of source code must retain the above copyright
universe@41 10 * notice, this list of conditions and the following disclaimer.
universe@41 11 *
universe@41 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@41 13 * notice, this list of conditions and the following disclaimer in the
universe@41 14 * documentation and/or other materials provided with the distribution.
universe@41 15 *
universe@41 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@41 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@41 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@41 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@41 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@41 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@41 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@41 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@41 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@41 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@41 26 * POSSIBILITY OF SUCH DAMAGE.
universe@41 27 *
universe@41 28 */
universe@41 29 package de.uapcore.lightpit.modules;
universe@41 30
universe@41 31
universe@41 32 import de.uapcore.lightpit.*;
universe@41 33 import de.uapcore.lightpit.dao.DataAccessObjects;
universe@64 34 import de.uapcore.lightpit.entities.*;
universe@86 35 import de.uapcore.lightpit.viewmodel.*;
universe@59 36 import org.slf4j.Logger;
universe@59 37 import org.slf4j.LoggerFactory;
universe@41 38
universe@41 39 import javax.servlet.annotation.WebServlet;
universe@41 40 import javax.servlet.http.HttpServletRequest;
universe@59 41 import javax.servlet.http.HttpServletResponse;
universe@59 42 import java.io.IOException;
universe@75 43 import java.sql.Date;
universe@47 44 import java.sql.SQLException;
universe@86 45 import java.util.NoSuchElementException;
universe@99 46 import java.util.Optional;
universe@83 47 import java.util.stream.Collectors;
universe@83 48 import java.util.stream.Stream;
universe@41 49
universe@52 50 import static de.uapcore.lightpit.Functions.fqn;
universe@52 51
universe@41 52 @WebServlet(
universe@41 53 name = "ProjectsModule",
universe@41 54 urlPatterns = "/projects/*"
universe@41 55 )
universe@41 56 public final class ProjectsModule extends AbstractLightPITServlet {
universe@41 57
universe@59 58 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
universe@59 59
universe@99 60 private static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project");
universe@99 61 private static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version");
universe@99 62 private static final String PARAMETER_SELECTED_PROJECT = "pid";
universe@99 63 private static final String PARAMETER_SELECTED_VERSION = "vid";
universe@71 64
universe@78 65 @Override
universe@78 66 protected String getResourceBundleName() {
universe@78 67 return "localization.projects";
universe@78 68 }
universe@71 69
universe@99 70 private int syncParamWithSession(HttpServletRequest req, String param, String attr) {
universe@99 71 final var session = req.getSession();
universe@99 72 final var idParam = getParameter(req, Integer.class, param);
universe@99 73 final int id;
universe@99 74 if (idParam.isPresent()) {
universe@99 75 id = idParam.get();
universe@99 76 session.setAttribute(attr, id);
universe@99 77 } else {
universe@99 78 id = Optional.ofNullable(session.getAttribute(attr)).map(x->(Integer)x).orElse(-1);
universe@99 79 }
universe@99 80 return id;
universe@99 81 }
universe@99 82
universe@99 83 private void populate(ProjectView viewModel, HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@99 84 final var projectDao = dao.getProjectDao();
universe@99 85 final var versionDao = dao.getVersionDao();
universe@99 86
universe@99 87 projectDao.list().stream().map(ProjectInfo::new).forEach(viewModel.getProjectList()::add);
universe@99 88
universe@99 89 // Select Project
universe@99 90 final int pid = syncParamWithSession(req, PARAMETER_SELECTED_PROJECT, SESSION_ATTR_SELECTED_PROJECT);
universe@99 91 if (pid >= 0) {
universe@99 92 final var project = projectDao.find(pid);
universe@107 93 if (project == null) {
universe@107 94 req.setAttribute(SESSION_ATTR_SELECTED_PROJECT, -1);
universe@107 95 } else {
universe@107 96 final var info = new ProjectInfo(project);
universe@107 97 info.setVersions(versionDao.list(project));
universe@107 98 info.setIssueSummary(projectDao.getIssueSummary(project));
universe@107 99 viewModel.setProjectInfo(info);
universe@107 100 }
universe@99 101 }
universe@99 102
universe@99 103 // Select Version
universe@99 104 final int vid = syncParamWithSession(req, PARAMETER_SELECTED_VERSION, SESSION_ATTR_SELECTED_VERSION);
universe@99 105 if (vid >= 0) {
universe@99 106 viewModel.setVersionFilter(versionDao.find(vid));
universe@99 107 }
universe@99 108 }
universe@99 109
universe@99 110 private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) {
universe@99 111 setViewModel(req, viewModel);
universe@99 112 setContentPage(req, name);
universe@99 113 setStylesheet(req, "projects");
universe@109 114 setNavigationMenu(req, "project-navmenu");
universe@99 115 return ResponseType.HTML;
universe@64 116 }
universe@64 117
universe@61 118 @RequestMapping(method = HttpMethod.GET)
universe@47 119 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@99 120 final var viewModel = new ProjectView();
universe@99 121 populate(viewModel, req, dao);
universe@86 122
universe@86 123 final var projectDao = dao.getProjectDao();
universe@86 124 final var versionDao = dao.getVersionDao();
universe@86 125
universe@99 126 for (var info : viewModel.getProjectList()) {
universe@99 127 info.setVersions(versionDao.list(info.getProject()));
universe@99 128 info.setIssueSummary(projectDao.getIssueSummary(info.getProject()));
universe@86 129 }
universe@86 130
universe@99 131 return forwardView(req, viewModel, "projects");
universe@45 132 }
universe@45 133
universe@99 134 private void configure(ProjectEditView viewModel, Project project, DataAccessObjects dao) throws SQLException {
universe@99 135 viewModel.setProject(project);
universe@86 136 viewModel.setUsers(dao.getUserDao().list());
universe@71 137 }
universe@71 138
universe@47 139 @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
universe@51 140 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@99 141 final var viewModel = new ProjectEditView();
universe@99 142 populate(viewModel, req, dao);
universe@47 143
universe@99 144 final var project = Optional.ofNullable(viewModel.getProjectInfo())
universe@99 145 .map(ProjectInfo::getProject)
universe@99 146 .orElse(new Project(-1));
universe@99 147 configure(viewModel, project, dao);
universe@47 148
universe@99 149 return forwardView(req, viewModel, "project-form");
universe@47 150 }
universe@47 151
universe@47 152 @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
universe@68 153 public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@47 154
universe@75 155 Project project = new Project(-1);
universe@47 156 try {
universe@99 157 project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
universe@47 158 project.setName(getParameter(req, String.class, "name").orElseThrow());
universe@47 159 getParameter(req, String.class, "description").ifPresent(project::setDescription);
universe@47 160 getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
universe@47 161 getParameter(req, Integer.class, "owner").map(
universe@47 162 ownerId -> ownerId >= 0 ? new User(ownerId) : null
universe@47 163 ).ifPresent(project::setOwner);
universe@47 164
universe@47 165 dao.getProjectDao().saveOrUpdate(project);
universe@47 166
universe@109 167 setRedirectLocation(req, "./projects/versions?pid="+project.getId());
universe@74 168 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@59 169 LOG.debug("Successfully updated project {}", project.getName());
universe@99 170
universe@99 171 return ResponseType.HTML;
universe@75 172 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@59 173 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@59 174 LOG.debug("Details:", ex);
universe@99 175 final var viewModel = new ProjectEditView();
universe@99 176 populate(viewModel, req, dao);
universe@99 177 configure(viewModel, project, dao);
universe@99 178 // TODO: error text
universe@99 179 return forwardView(req, viewModel, "project-form");
universe@47 180 }
universe@47 181 }
universe@47 182
universe@70 183 @RequestMapping(requestPath = "view", method = HttpMethod.GET)
universe@80 184 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
universe@99 185 final var viewModel = new ProjectDetailsView();
universe@99 186 populate(viewModel, req, dao);
universe@86 187
universe@99 188 if (viewModel.getProjectInfo() == null) {
universe@80 189 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
universe@80 190 return ResponseType.NONE;
universe@80 191 }
universe@47 192
universe@86 193 final var issueDao = dao.getIssueDao();
universe@70 194
universe@105 195 final var version = viewModel.getVersionFilter();
universe@99 196
universe@99 197 final var detailView = viewModel.getProjectDetails();
universe@105 198 final var issues = issueDao.list(version);
universe@100 199 for (var issue : issues) issueDao.joinVersionInformation(issue);
universe@105 200 detailView.updateDetails(issues, version);
universe@80 201
universe@99 202 return forwardView(req, viewModel, "project-details");
universe@71 203 }
universe@71 204
universe@109 205 @RequestMapping(requestPath = "versions", method = HttpMethod.GET)
universe@109 206 public ResponseType versions(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
universe@109 207 final var viewModel = new VersionsView();
universe@109 208 populate(viewModel, req, dao);
universe@109 209 viewModel.setVersionFilter(null);
universe@109 210
universe@109 211 final var projectInfo = viewModel.getProjectInfo();
universe@109 212 if (projectInfo == null) {
universe@109 213 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
universe@109 214 return ResponseType.NONE;
universe@109 215 }
universe@109 216
universe@109 217 final var issueDao = dao.getIssueDao();
universe@109 218 final var issues = issueDao.list(projectInfo.getProject());
universe@109 219 for (var issue : issues) issueDao.joinVersionInformation(issue);
universe@109 220 viewModel.update(projectInfo.getVersions(), issues);
universe@109 221
universe@109 222 return forwardView(req, viewModel, "versions");
universe@109 223 }
universe@109 224
universe@59 225 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
universe@86 226 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@99 227 final var viewModel = new VersionEditView();
universe@99 228 populate(viewModel, req, dao);
universe@99 229
universe@99 230 if (viewModel.getVersionFilter() == null) {
universe@99 231 viewModel.setVersion(new Version(-1));
universe@86 232 } else {
universe@99 233 viewModel.setVersion(viewModel.getVersionFilter());
universe@86 234 }
universe@59 235
universe@99 236 return forwardView(req, viewModel, "version-form");
universe@59 237 }
universe@59 238
universe@59 239 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
universe@80 240 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@59 241
universe@86 242 var version = new Version(-1);
universe@59 243 try {
universe@86 244 version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
universe@86 245 version.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
universe@59 246 version.setName(getParameter(req, String.class, "name").orElseThrow());
universe@59 247 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
universe@59 248 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
universe@59 249 dao.getVersionDao().saveOrUpdate(version);
universe@59 250
universe@75 251 // specifying the pid parameter will purposely reset the session selected version!
universe@109 252 setRedirectLocation(req, "./projects/versions?pid=" + version.getProject().getId());
universe@74 253 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@75 254 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@59 255 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@59 256 LOG.debug("Details:", ex);
universe@99 257 final var viewModel = new VersionEditView();
universe@99 258 populate(viewModel, req, dao);
universe@99 259 viewModel.setVersion(version);
universe@86 260 // TODO: set Error Text
universe@99 261 return forwardView(req, viewModel, "version-form");
universe@59 262 }
universe@41 263
universe@43 264 return ResponseType.HTML;
universe@41 265 }
universe@64 266
universe@99 267 private void configure(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException {
universe@99 268 issue.setProject(viewModel.getProjectInfo().getProject());
universe@99 269 viewModel.setIssue(issue);
universe@99 270 viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions());
universe@86 271 viewModel.setUsers(dao.getUserDao().list());
universe@71 272 }
universe@71 273
universe@64 274 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
universe@80 275 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@99 276 final var viewModel = new IssueEditView();
universe@99 277
universe@99 278 final var issueParam = getParameter(req, Integer.class, "issue");
universe@99 279 if (issueParam.isPresent()) {
universe@104 280 final var issueDao = dao.getIssueDao();
universe@104 281 final var issue = issueDao.find(issueParam.get());
universe@104 282 issueDao.joinVersionInformation(issue);
universe@99 283 req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, issue.getProject().getId());
universe@99 284 populate(viewModel, req, dao);
universe@99 285 configure(viewModel, issue, dao);
universe@86 286 } else {
universe@99 287 populate(viewModel, req, dao);
universe@99 288 configure(viewModel, new Issue(-1), dao);
universe@86 289 }
universe@64 290
universe@99 291 return forwardView(req, viewModel, "issue-form");
universe@64 292 }
universe@64 293
universe@64 294 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
universe@80 295 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@86 296 Issue issue = new Issue(-1);
universe@64 297 try {
universe@86 298 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
universe@86 299 issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
universe@75 300 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
universe@75 301 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
universe@75 302 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow());
universe@75 303 getParameter(req, Integer.class, "assignee").map(
universe@75 304 userid -> userid >= 0 ? new User(userid) : null
universe@75 305 ).ifPresent(issue::setAssignee);
universe@75 306 getParameter(req, String.class, "description").ifPresent(issue::setDescription);
universe@75 307 getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
universe@83 308
universe@83 309 getParameter(req, Integer[].class, "affected")
universe@83 310 .map(Stream::of)
universe@83 311 .map(stream ->
universe@96 312 stream.map(Version::new).collect(Collectors.toList())
universe@83 313 ).ifPresent(issue::setAffectedVersions);
universe@83 314 getParameter(req, Integer[].class, "resolved")
universe@83 315 .map(Stream::of)
universe@83 316 .map(stream ->
universe@86 317 stream.map(Version::new).collect(Collectors.toList())
universe@83 318 ).ifPresent(issue::setResolvedVersions);
universe@83 319
universe@64 320 dao.getIssueDao().saveOrUpdate(issue);
universe@64 321
universe@96 322 // specifying the issue parameter keeps the edited issue as menu item
universe@102 323 setRedirectLocation(req, "./projects/view?pid=" + issue.getProject().getId());
universe@74 324 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@75 325 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@64 326 // TODO: set request attribute with error text
universe@64 327 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@64 328 LOG.debug("Details:", ex);
universe@99 329 final var viewModel = new IssueEditView();
universe@99 330 configure(viewModel, issue, dao);
universe@86 331 // TODO: set Error Text
universe@99 332 return forwardView(req, viewModel, "issue-form");
universe@64 333 }
universe@64 334
universe@64 335 return ResponseType.HTML;
universe@64 336 }
universe@41 337 }

mercurial