src/main/java/de/uapcore/lightpit/dao/postgres/PGIssueDao.java

Fri, 23 Oct 2020 20:34:57 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 23 Oct 2020 20:34:57 +0200
changeset 150
822b7e3d064d
parent 138
e2aa673dd473
child 154
3d10f2a390a1
permissions
-rw-r--r--

migrate entities package

     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.dao.postgres;
    31 import de.uapcore.lightpit.dao.IssueDao;
    32 import de.uapcore.lightpit.entities.*;
    34 import java.sql.*;
    35 import java.util.ArrayList;
    36 import java.util.List;
    37 import java.util.Objects;
    38 import java.util.Optional;
    40 import static de.uapcore.lightpit.dao.Functions.*;
    42 public final class PGIssueDao implements IssueDao {
    44     private final PreparedStatement insert, update, list, listForVersion, find;
    45     private final PreparedStatement affectedVersions, resolvedVersions;
    46     private final PreparedStatement clearAffected, clearResolved;
    47     private final PreparedStatement insertAffected, insertResolved;
    48     private final PreparedStatement insertComment, updateComment, listComments;
    50     public PGIssueDao(Connection connection) throws SQLException {
    51         final var query = "select issueid, i.project, p.name as projectname, p.node as projectnode, "+
    52                         "component, c.name as componentname, c.node as componentnode, " +
    53                         "status, category, subject, i.description, " +
    54                         "userid, username, givenname, lastname, mail, " +
    55                         "created, updated, eta " +
    56                         "from lpit_issue i " +
    57                         "join lpit_project p on i.project = projectid " +
    58                         "left join lpit_component c on component = c.id " +
    59                         "left join lpit_user on userid = assignee ";
    61         list = connection.prepareStatement(query +
    62                         "where i.project = ? and coalesce(component, -1) = coalesce(?, component, -1)");
    64         listForVersion = connection.prepareStatement(
    65                 "with issue_version as ( "+
    66                         "select issueid, versionid from lpit_issue_affected_version union "+
    67                         "select issueid, versionid from lpit_issue_resolved_version) "+
    68                         query +
    69                         "left join issue_version using (issueid) "+
    70                         "where coalesce(versionid,-1) = ? and coalesce(component, -1) = coalesce(?, component, -1)"
    71         );
    73         find = connection.prepareStatement(query + "where issueid = ? ");
    75         insert = connection.prepareStatement(
    76                 "insert into lpit_issue (project, component, status, category, subject, description, assignee, eta) " +
    77                         "values (?, ?, ?::issue_status, ?::issue_category, ?, ?, ?, ?) returning issueid"
    78         );
    79         update = connection.prepareStatement(
    80                 "update lpit_issue set " +
    81                         "updated = now(), component = ?, status = ?::issue_status, category = ?::issue_category, " +
    82                         "subject = ?, description = ?, assignee = ?, eta = ? where issueid = ?"
    83         );
    85         affectedVersions = connection.prepareStatement(
    86                 "select versionid, name, status, ordinal " +
    87                         "from lpit_version join lpit_issue_affected_version using (versionid) " +
    88                         "where issueid = ? " +
    89                         "order by ordinal, name"
    90         );
    91         clearAffected = connection.prepareStatement("delete from lpit_issue_affected_version where issueid = ?");
    92         insertAffected = connection.prepareStatement("insert into lpit_issue_affected_version (issueid, versionid) values (?,?)");
    94         resolvedVersions = connection.prepareStatement(
    95                 "select versionid, name, status, ordinal " +
    96                         "from lpit_version v join lpit_issue_resolved_version using (versionid) " +
    97                         "where issueid = ? " +
    98                         "order by ordinal, name"
    99         );
   100         clearResolved = connection.prepareStatement("delete from lpit_issue_resolved_version where issueid = ?");
   101         insertResolved = connection.prepareStatement("insert into lpit_issue_resolved_version (issueid, versionid) values (?,?)");
   103         insertComment = connection.prepareStatement(
   104                 "insert into lpit_issue_comment (issueid, comment, userid) values (?, ? ,?)"
   105         );
   106         updateComment = connection.prepareStatement(
   107                 "update lpit_issue_comment set comment = ?, updated = now(), updatecount = updatecount+1 where commentid = ?"
   108         );
   109         listComments = connection.prepareStatement(
   110                 "select * from lpit_issue_comment left join lpit_user using (userid) where issueid = ? order by created"
   111         );
   112     }
   114     private Issue mapColumns(ResultSet result) throws SQLException {
   115         final var project = new Project(result.getInt("project"));
   116         project.setName(result.getString("projectname"));
   117         project.setNode(result.getString("projectnode"));
   118         var component = new Component(result.getInt("component"));
   119         if (result.wasNull()) {
   120             component = null;
   121         } else {
   122             component.setName(result.getString("componentname"));
   123             component.setNode(result.getString("componentnode"));
   124         }
   125         final var issue = new Issue(result.getInt("issueid"));
   126         issue.setProject(project);
   127         issue.setComponent(component);
   128         issue.setStatus(IssueStatus.valueOf(result.getString("status")));
   129         issue.setCategory(IssueCategory.valueOf(result.getString("category")));
   130         issue.setSubject(result.getString("subject"));
   131         issue.setDescription(result.getString("description"));
   132         issue.setAssignee(PGUserDao.mapColumns(result));
   133         issue.setCreated(result.getTimestamp("created"));
   134         issue.setUpdated(result.getTimestamp("updated"));
   135         issue.setEta(result.getDate("eta"));
   136         return issue;
   137     }
   139     private Version mapVersion(ResultSet result) throws SQLException {
   140         final var version = new Version(result.getInt("versionid"));
   141         version.setName(result.getString("name"));
   142         version.setOrdinal(result.getInt("ordinal"));
   143         version.setStatus(VersionStatus.valueOf(result.getString("status")));
   144         return version;
   145     }
   147     private void updateVersionLists(Issue instance) throws SQLException {
   148         clearAffected.setInt(1, instance.getId());
   149         clearResolved.setInt(1, instance.getId());
   150         insertAffected.setInt(1, instance.getId());
   151         insertResolved.setInt(1, instance.getId());
   152         clearAffected.executeUpdate();
   153         clearResolved.executeUpdate();
   154         for (Version v : instance.getAffectedVersions()) {
   155             insertAffected.setInt(2, v.getId());
   156             insertAffected.executeUpdate();
   157         }
   158         for (Version v : instance.getResolvedVersions()) {
   159             insertResolved.setInt(2, v.getId());
   160             insertResolved.executeUpdate();
   161         }
   162     }
   164     private int setData(PreparedStatement stmt, int column, Issue instance) throws SQLException {
   165         setForeignKeyOrNull(stmt, ++column, instance.getComponent(), Component::getId);
   166         stmt.setString(++column, instance.getStatus().name());
   167         stmt.setString(++column, instance.getCategory().name());
   168         stmt.setString(++column, instance.getSubject());
   169         setStringOrNull(stmt, ++column, instance.getDescription());
   170         setForeignKeyOrNull(stmt, ++column, instance.getAssignee(), User::getId);
   171         setDateOrNull(stmt, ++column, instance.getEta());
   172         return column;
   173     }
   175     @Override
   176     public void save(Issue instance, Project project) throws SQLException {
   177         Objects.requireNonNull(instance.getSubject());
   178         instance.setProject(project);
   179         int column = 0;
   180         insert.setInt(++column, instance.getProject().getId());
   181         setData(insert, column, instance);
   182         // insert and retrieve the ID
   183         final var rs = insert.executeQuery();
   184         rs.next();
   185         instance.setId(rs.getInt(1));
   186         updateVersionLists(instance);
   187     }
   189     @Override
   190     public boolean update(Issue instance) throws SQLException {
   191         if (instance.getId() < 0) return false;
   192         Objects.requireNonNull(instance.getSubject());
   193         int column = setData(update, 0, instance);
   194         update.setInt(++column, instance.getId());
   195         boolean success = update.executeUpdate() > 0;
   196         if (success) {
   197             updateVersionLists(instance);
   198             return true;
   199         } else {
   200             return false;
   201         }
   202     }
   204     private List<Issue> executeQuery(PreparedStatement query) throws SQLException {
   205         List<Issue> issues = new ArrayList<>();
   206         try (var result = query.executeQuery()) {
   207             while (result.next()) {
   208                 issues.add(mapColumns(result));
   209             }
   210         }
   211         return issues;
   212     }
   214     @Override
   215     public List<Issue> list(Project project) throws SQLException {
   216         list.setInt(1, project.getId());
   217         list.setNull(2, Types.INTEGER);
   218         return executeQuery(list);
   219     }
   221     @Override
   222     public List<Issue> list(Project project, Component component, Version version) throws SQLException {
   223         listForVersion.setInt(1, Optional.ofNullable(version).map(Version::getId).orElse(-1));
   224         listForVersion.setInt(2, Optional.ofNullable(component).map(Component::getId).orElse(-1));
   225         return executeQuery(listForVersion);
   226     }
   228     @Override
   229     public List<Issue> list(Project project, Version version) throws SQLException {
   230         listForVersion.setInt(1, Optional.ofNullable(version).map(Version::getId).orElse(-1));
   231         listForVersion.setNull(2, Types.INTEGER);
   232         return executeQuery(listForVersion);
   233     }
   235     @Override
   236     public List<Issue> list(Project project, Component component) throws SQLException {
   237         list.setInt(1, project.getId());
   238         list.setInt(2, Optional.ofNullable(component).map(Component::getId).orElse(-1));
   239         return executeQuery(list);
   240     }
   242     @Override
   243     public Issue find(int id) throws SQLException {
   244         find.setInt(1, id);
   245         try (var result = find.executeQuery()) {
   246             if (result.next()) {
   247                 return mapColumns(result);
   248             } else {
   249                 return null;
   250             }
   251         }
   252     }
   254     private List<Version> listVersions(PreparedStatement stmt, Issue issue) throws SQLException {
   255         stmt.setInt(1, issue.getId());
   256         List<Version> versions = new ArrayList<>();
   257         try (var result = stmt.executeQuery()) {
   258             while (result.next()) {
   259                 versions.add(mapVersion(result));
   260             }
   261         }
   262         return versions;
   263     }
   265     @Override
   266     public void joinVersionInformation(Issue issue) throws SQLException {
   267         Objects.requireNonNull(issue.getProject());
   268         issue.setAffectedVersions(listVersions(affectedVersions, issue));
   269         issue.setResolvedVersions(listVersions(resolvedVersions, issue));
   270     }
   272     @Override
   273     public List<IssueComment> listComments(Issue issue) throws SQLException {
   274         listComments.setInt(1, issue.getId());
   275         List<IssueComment> comments = new ArrayList<>();
   276         try (var result = listComments.executeQuery()) {
   277             while (result.next()) {
   278                 final var comment = new IssueComment(result.getInt("commentid"));
   279                 comment.setCreated(result.getTimestamp("created"));
   280                 comment.setUpdated(result.getTimestamp("updated"));
   281                 comment.setUpdateCount(result.getInt("updatecount"));
   282                 comment.setComment(result.getString("comment"));
   283                 comment.setAuthor(PGUserDao.mapColumns(result));
   284                 comments.add(comment);
   285             }
   286         }
   287         return comments;
   288     }
   290     @Override
   291     public void saveComment(Issue issue, IssueComment comment) throws SQLException {
   292         if (comment.getId() >= 0) {
   293             updateComment.setString(1, comment.getComment());
   294             updateComment.setInt(2, comment.getId());
   295             updateComment.execute();
   296         } else {
   297             insertComment.setInt(1, issue.getId());
   298             insertComment.setString(2, comment.getComment());
   299             setForeignKeyOrNull(insertComment, 3, comment.getAuthor(), User::getId);
   300             insertComment.execute();
   301         }
   302     }
   303 }

mercurial