adds data model for issues

Mon, 18 May 2020 21:05:57 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 18 May 2020 21:05:57 +0200
changeset 62
833e0385572a
parent 61
3e287f361c7a
child 63
51aa5e267c7f

adds data model for issues

setup/postgres/psql_create_tables.sql file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/Functions.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/GenericDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/IssueDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/ProjectDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/UserDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/VersionDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGIssueDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Issue.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/IssueCategory.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/IssueStatus.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Version.java file | annotate | diff | comparison | revisions
--- a/setup/postgres/psql_create_tables.sql	Sun May 17 16:38:04 2020 +0200
+++ b/setup/postgres/psql_create_tables.sql	Mon May 18 21:05:57 2020 +0200
@@ -32,3 +32,36 @@
     ordinal         integer         not null default 0,
     status          version_status  not null default 'Future'
 );
+
+create type issue_status as enum (
+    'InSpecification',
+    'ToDo',
+    'Scheduled',
+    'InProgress',
+    'InReview',
+    'Done',
+    'Rejected',
+    'Withdrawn'
+);
+
+create type issue_category as enum (
+    'Feature',
+    'Improvement',
+    'Bug',
+    'Task',
+    'Test'
+);
+
+create table lpit_issue (
+    id              serial          primary key,
+    project         integer         not null references lpit_project(id),
+    status          issue_status    not null default 'InSpecification',
+    category        issue_category  not null default 'Feature',
+    subject         varchar(20)     not null,
+    description     text,
+    version_plan    integer         references lpit_version(id),
+    version_done    integer         references lpit_version(id),
+    created         timestamp       with time zone not null default now(),
+    updated         timestamp       with time zone not null default now(),
+    eta             date
+);
--- a/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java	Mon May 18 21:05:57 2020 +0200
@@ -32,4 +32,5 @@
     UserDao getUserDao();
     ProjectDao getProjectDao();
     VersionDao getVersionDao();
+    IssueDao getIssueDao();
 }
--- a/src/main/java/de/uapcore/lightpit/dao/Functions.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/Functions.java	Mon May 18 21:05:57 2020 +0200
@@ -28,6 +28,7 @@
  */
 package de.uapcore.lightpit.dao;
 
+import java.sql.Date;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Types;
@@ -47,6 +48,14 @@
         }
     }
 
+    public static void setDateOrNull(PreparedStatement stmt, int index, Date date) throws SQLException {
+        if (date == null) {
+            stmt.setNull(index, Types.DATE);
+        } else {
+            stmt.setDate(index, date);
+        }
+    }
+
     public static <T> void setForeignKeyOrNull(PreparedStatement stmt, int index, T instance, Function<? super T, Integer> keyGetter) throws SQLException {
         Integer key = Optional.ofNullable(instance).map(keyGetter).orElse(null);
         if (key == null) {
--- a/src/main/java/de/uapcore/lightpit/dao/GenericDao.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/GenericDao.java	Mon May 18 21:05:57 2020 +0200
@@ -29,16 +29,8 @@
 package de.uapcore.lightpit.dao;
 
 import java.sql.SQLException;
-import java.util.List;
 
 public interface GenericDao<T> {
-    /**
-     * Returns a list of all entities.
-     *
-     * @return a list of all objects
-     * @throws SQLException on any kind of SQL errors
-     */
-    List<T> list() throws SQLException;
 
     /**
      * Finds an entity by its integer ID.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/dao/IssueDao.java	Mon May 18 21:05:57 2020 +0200
@@ -0,0 +1,46 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package de.uapcore.lightpit.dao;
+
+import de.uapcore.lightpit.entities.Issue;
+import de.uapcore.lightpit.entities.Project;
+
+import java.sql.SQLException;
+import java.util.List;
+
+public interface IssueDao extends GenericDao<Issue> {
+
+    /**
+     * Lists all issues for the specified project.
+     * @param project the project
+     * @return a list of issues
+     * @throws SQLException on any kind of SQL error
+     */
+    List<Issue> list(Project project) throws SQLException;
+}
--- a/src/main/java/de/uapcore/lightpit/dao/ProjectDao.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/ProjectDao.java	Mon May 18 21:05:57 2020 +0200
@@ -30,5 +30,9 @@
 
 import de.uapcore.lightpit.entities.Project;
 
+import java.sql.SQLException;
+import java.util.List;
+
 public interface ProjectDao extends GenericDao<Project> {
+    List<Project> list() throws SQLException;
 }
--- a/src/main/java/de/uapcore/lightpit/dao/UserDao.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/UserDao.java	Mon May 18 21:05:57 2020 +0200
@@ -30,6 +30,10 @@
 
 import de.uapcore.lightpit.entities.User;
 
+import java.sql.SQLException;
+import java.util.List;
+
 public interface UserDao extends GenericDao<User> {
 
+    List<User> list() throws SQLException;
 }
--- a/src/main/java/de/uapcore/lightpit/dao/VersionDao.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/VersionDao.java	Mon May 18 21:05:57 2020 +0200
@@ -34,14 +34,7 @@
 import java.sql.SQLException;
 import java.util.List;
 
-public interface VersionDao {
-
-    Version find(int id) throws SQLException;
-    void save(Version instance) throws SQLException;
-    boolean update(Version instance) throws SQLException;
-    default void saveOrUpdate(Version instance) throws SQLException {
-        if (!update(instance)) save(instance);
-    }
+public interface VersionDao extends GenericDao<Version> {
 
     /**
      * Lists all versions for the specified project.
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java	Mon May 18 21:05:57 2020 +0200
@@ -28,10 +28,7 @@
  */
 package de.uapcore.lightpit.dao.postgres;
 
-import de.uapcore.lightpit.dao.DataAccessObjects;
-import de.uapcore.lightpit.dao.ProjectDao;
-import de.uapcore.lightpit.dao.UserDao;
-import de.uapcore.lightpit.dao.VersionDao;
+import de.uapcore.lightpit.dao.*;
 
 import java.sql.Connection;
 import java.sql.SQLException;
@@ -41,11 +38,13 @@
     private final UserDao userDao;
     private final ProjectDao projectDao;
     private final VersionDao versionDao;
+    private final IssueDao issueDao;
 
     public PGDataAccessObjects(Connection connection) throws SQLException {
         userDao = new PGUserDao(connection);
         projectDao = new PGProjectDao(connection);
         versionDao = new PGVersionDao(connection);
+        issueDao = new PGIssueDao(connection);
     }
 
     @Override
@@ -62,4 +61,9 @@
     public VersionDao getVersionDao() {
         return versionDao;
     }
+
+    @Override
+    public IssueDao getIssueDao() {
+        return issueDao;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGIssueDao.java	Mon May 18 21:05:57 2020 +0200
@@ -0,0 +1,155 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package de.uapcore.lightpit.dao.postgres;
+
+import de.uapcore.lightpit.dao.IssueDao;
+import de.uapcore.lightpit.entities.*;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static de.uapcore.lightpit.dao.Functions.*;
+
+public final class PGIssueDao implements IssueDao {
+
+    private final PreparedStatement insert, update, list, find;
+
+    public PGIssueDao(Connection connection) throws SQLException {
+        list = connection.prepareStatement(
+                "select id, project, status, category, subject, description, " +
+                        "vplan.id, vplan.name, vdone.id, vdone.name, " +
+                        "created, updated, eta " +
+                        "from lpit_issue " +
+                        "left join lpit_version vplan on vplan.id = version_plan " +
+                        "left join lpit_version vdone on vdone.id = version_done " +
+                        "where project = ? ");
+
+        find = connection.prepareStatement(
+                "select id, project, status, category, subject, description, " +
+                        "vplan.id, vplan.name, vdone.id, vdone.name, " +
+                        "created, updated, eta " +
+                        "from lpit_issue " +
+                        "left join lpit_version vplan on vplan.id = version_plan " +
+                        "left join lpit_version vdone on vdone.id = version_done " +
+                        "where id = ? ");
+
+        insert = connection.prepareStatement(
+                "insert into lpit_issue (project, status, category, subject, description, version_plan, version_done, eta) " +
+                        "values (?, ?::issue_status, ?::issue_category, ?, ?, ?, ?, ?)"
+        );
+        update = connection.prepareStatement(
+                "update lpit_issue set updated = now(), status = ?::issue_status, category = ?::issue_category, " +
+                        "subject = ?, description = ?, version_plan = ?, version_done = ?, eta = ? where id = ?"
+        );
+    }
+
+    private Version obtainVersion(ResultSet result, Project project, String prefix) throws SQLException {
+        final int vplan = result.getInt(prefix+"id");
+        if (vplan > 0) {
+            final var ver = new Version(vplan, project);
+            ver.setName(result.getString(prefix+"name"));
+            return ver;
+        } else {
+            return null;
+        }
+    }
+
+    public Issue mapColumns(ResultSet result) throws SQLException {
+        final var project = new Project(result.getInt("project"));
+        final var issue = new Issue(result.getInt("id"), project);
+        issue.setStatus(IssueStatus.valueOf(result.getString("status")));
+        issue.setCategory(IssueCategory.valueOf(result.getString("category")));
+        issue.setSubject(result.getString("subject"));
+        issue.setDescription(result.getString("description"));
+        issue.setScheduledVersion(obtainVersion(result, project, "vplan."));
+        issue.setResolvedVersion(obtainVersion(result, project, "vdone."));
+        issue.setCreated(result.getTimestamp("created"));
+        issue.setUpdated(result.getTimestamp("updated"));
+        issue.setEta(result.getDate("eta"));
+        return issue;
+    }
+
+    @Override
+    public void save(Issue instance) throws SQLException {
+        Objects.requireNonNull(instance.getSubject());
+        Objects.requireNonNull(instance.getProject());
+        insert.setInt(1, instance.getProject().getId());
+        insert.setString(2, instance.getStatus().name());
+        insert.setString(3, instance.getCategory().name());
+        insert.setString(4, instance.getSubject());
+        setStringOrNull(insert, 5, instance.getDescription());
+        setForeignKeyOrNull(insert, 6, instance.getScheduledVersion(), Version::getId);
+        setForeignKeyOrNull(insert, 7, instance.getResolvedVersion(), Version::getId);
+        setDateOrNull(insert, 8, instance.getEta());
+        insert.executeUpdate();
+    }
+
+    @Override
+    public boolean update(Issue instance) throws SQLException {
+        Objects.requireNonNull(instance.getSubject());
+        update.setString(1, instance.getStatus().name());
+        update.setString(2, instance.getCategory().name());
+        update.setString(3, instance.getSubject());
+        setStringOrNull(update, 4, instance.getDescription());
+        setForeignKeyOrNull(update, 5, instance.getScheduledVersion(), Version::getId);
+        setForeignKeyOrNull(update, 6, instance.getResolvedVersion(), Version::getId);
+        setDateOrNull(update, 7, instance.getEta());
+        update.setInt(8, instance.getId());
+        return update.executeUpdate() > 0;
+    }
+
+    @Override
+    public List<Issue> list(Project project) throws SQLException {
+        list.setInt(1, project.getId());
+        List<Issue> versions = new ArrayList<>();
+        try (var result = list.executeQuery()) {
+            while (result.next()) {
+                versions.add(mapColumns(result));
+            }
+        }
+        return versions;
+    }
+
+    @Override
+    public Issue find(int id) throws SQLException {
+        find.setInt(1, id);
+        try (var result = find.executeQuery()) {
+            if (result.next()) {
+                return mapColumns(result);
+            } else {
+                return null;
+            }
+        }
+    }
+}
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java	Mon May 18 21:05:57 2020 +0200
@@ -50,7 +50,7 @@
                 "select id, project, name, ordinal, status " +
                         "from lpit_version " +
                         "where project = ? " +
-                        "order by ordinal, name");
+                        "order by ordinal, lower(name)");
 
         find = connection.prepareStatement(
                 "select id, project, name, ordinal, status " +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/entities/Issue.java	Mon May 18 21:05:57 2020 +0200
@@ -0,0 +1,160 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package de.uapcore.lightpit.entities;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Objects;
+
+public final class Issue {
+
+    private final int id;
+    private final Project project;
+
+    private IssueStatus status;
+    private IssueCategory category;
+
+    private String subject;
+    private String description;
+
+    private List<Version> affectedVersions;
+    private Version scheduledVersion;
+    private Version resolvedVersion;
+
+    private Timestamp created;
+    private Timestamp updated;
+    private Date eta;
+
+    public Issue(int id, Project project) {
+        this.id = id;
+        this.project = project;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public Project getProject() {
+        return project;
+    }
+
+    public IssueStatus getStatus() {
+        return status;
+    }
+
+    public void setStatus(IssueStatus status) {
+        this.status = status;
+    }
+
+    public IssueCategory getCategory() {
+        return category;
+    }
+
+    public void setCategory(IssueCategory category) {
+        this.category = category;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public List<Version> getAffectedVersions() {
+        return affectedVersions;
+    }
+
+    public void setAffectedVersions(List<Version> affectedVersions) {
+        this.affectedVersions = affectedVersions;
+    }
+
+    public Version getScheduledVersion() {
+        return scheduledVersion;
+    }
+
+    public void setScheduledVersion(Version scheduledVersion) {
+        this.scheduledVersion = scheduledVersion;
+    }
+
+    public Version getResolvedVersion() {
+        return resolvedVersion;
+    }
+
+    public void setResolvedVersion(Version resolvedVersion) {
+        this.resolvedVersion = resolvedVersion;
+    }
+
+    public Timestamp getCreated() {
+        return created;
+    }
+
+    public void setCreated(Timestamp created) {
+        this.created = created;
+    }
+
+    public Timestamp getUpdated() {
+        return updated;
+    }
+
+    public void setUpdated(Timestamp updated) {
+        this.updated = updated;
+    }
+
+    public Date getEta() {
+        return eta;
+    }
+
+    public void setEta(Date eta) {
+        this.eta = eta;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Issue issue = (Issue) o;
+        return id == issue.id;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/entities/IssueCategory.java	Mon May 18 21:05:57 2020 +0200
@@ -0,0 +1,37 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package de.uapcore.lightpit.entities;
+
+public enum IssueCategory {
+    Feature,
+    Improvement,
+    Bug,
+    Task,
+    Test
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/entities/IssueStatus.java	Mon May 18 21:05:57 2020 +0200
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2018 Mike Becker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package de.uapcore.lightpit.entities;
+
+public enum IssueStatus {
+    InSpecification,
+    ToDo,
+    Scheduled,
+    InProgress,
+    InReview,
+    Done,
+    Rejected,
+    Withdrawn
+}
--- a/src/main/java/de/uapcore/lightpit/entities/Version.java	Sun May 17 16:38:04 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/entities/Version.java	Mon May 18 21:05:57 2020 +0200
@@ -30,7 +30,7 @@
 
 import java.util.Objects;
 
-public class Version implements Comparable<Version> {
+public final class Version implements Comparable<Version> {
 
     private final int id;
     private final Project project;

mercurial