adds DAO for Project entity and save/update methods

Mon, 11 May 2020 19:09:06 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 11 May 2020 19:09:06 +0200
changeset 38
cf85ef18f231
parent 37
fecda0f466e6
child 39
e722861558bb

adds DAO for Project entity and save/update methods

src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/DatabaseFacade.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/AbstractDao.java 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/GenericDao.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/postgres/PGDataAccessObjects.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Project.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Version.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/VersionStatus.java file | annotate | diff | comparison | revisions
--- a/src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java	Mon May 11 19:09:06 2020 +0200
@@ -28,6 +28,8 @@
  */
 package de.uapcore.lightpit;
 
+import de.uapcore.lightpit.dao.DataAccessObjects;
+import de.uapcore.lightpit.dao.postgres.PGDataAccessObjects;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,6 +41,8 @@
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.sql.Connection;
+import java.sql.SQLException;
 import java.util.*;
 
 /**
@@ -59,7 +63,7 @@
 
     @FunctionalInterface
     private interface HandlerMethod {
-        ResponseType apply(HttpServletRequest t, HttpServletResponse u) throws IOException;
+        ResponseType apply(HttpServletRequest request, HttpServletResponse response, DataAccessObjects dao) throws IOException, SQLException;
     }
 
     /**
@@ -82,21 +86,30 @@
         return (ModuleManager) getServletContext().getAttribute(ModuleManager.SC_ATTR_NAME);
     }
 
+
     /**
-     * Gives implementing modules access to the {@link DatabaseFacade}.
+     * Creates a set of data access objects for the specified connection.
      *
-     * @return the database facade
+     * @param connection the SQL connection
+     * @return a set of data access objects
      */
-    protected final DatabaseFacade getDatabaseFacade() {
-        return (DatabaseFacade) getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME);
+    private DataAccessObjects createDataAccessObjects(Connection connection) throws SQLException {
+        final var df = (DatabaseFacade) getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME);
+        switch (df.getSQLDialect()) {
+            case Postgres:
+                return new PGDataAccessObjects(connection);
+            default:
+                throw new AssertionError("Non-exhaustive switch - this is a bug.");
+        }
     }
 
-    private ResponseType invokeMapping(Method method, HttpServletRequest req, HttpServletResponse resp) throws IOException {
+    private ResponseType invokeMapping(Method method, HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException {
         try {
             LOG.trace("invoke {}#{}", method.getDeclaringClass().getName(), method.getName());
-            return (ResponseType) method.invoke(this, req, resp);
+            return (ResponseType) method.invoke(this, req, resp, dao);
         } catch (ReflectiveOperationException | ClassCastException ex) {
-            LOG.error(String.format("invocation of method %s failed", method.getName()), ex);
+            LOG.error("invocation of method {} failed: {}", method.getName(), ex.getMessage());
+            LOG.debug("Details: ", ex);
             resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
             return ResponseType.NONE;
         }
@@ -140,15 +153,16 @@
                     }
 
                     Class<?>[] params = method.getParameterTypes();
-                    if (params.length == 2
+                    if (params.length == 3
                             && HttpServletRequest.class.isAssignableFrom(params[0])
-                            && HttpServletResponse.class.isAssignableFrom(params[1])) {
+                            && HttpServletResponse.class.isAssignableFrom(params[1])
+                            && DataAccessObjects.class.isAssignableFrom(params[2])) {
 
                         final String requestPath = "/" + mapping.get().requestPath();
 
                         if (mappings.computeIfAbsent(mapping.get().method(), k -> new HashMap<>()).
                                 putIfAbsent(requestPath,
-                                        (req, resp) -> invokeMapping(method, req, resp)) != null) {
+                                        (req, resp, dao) -> invokeMapping(method, req, resp, dao)) != null) {
                             LOG.warn("{} {} has multiple mappings",
                                     mapping.get().method(),
                                     mapping.get().requestPath()
@@ -238,8 +252,7 @@
         }
     }
 
-    private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp)
-            throws ServletException, IOException {
+    private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         // choose the requested language as session language (if available) or fall back to english, otherwise
         HttpSession session = req.getSession();
@@ -260,13 +273,21 @@
         req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName());
         Optional.ofNullable(moduleInfo).ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy));
 
-
-        // call the handler, if available, or send an HTTP 404 error
-        Optional<HandlerMethod> mapping = findMapping(method, req);
-        if (mapping.isPresent()) {
-            forwardAsSpecified(mapping.get().apply(req, resp), req, resp);
-        } else {
-            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+        // obtain a connection and create the data access objects
+        final var db = (DatabaseFacade) req.getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME);
+        try (final var connection = db.getDataSource().getConnection()) {
+            final var dao = createDataAccessObjects(connection);
+            // call the handler, if available, or send an HTTP 404 error
+            final var mapping = findMapping(method, req);
+            if (mapping.isPresent()) {
+                forwardAsSpecified(mapping.get().apply(req, resp, dao), req, resp);
+            } else {
+                resp.sendError(HttpServletResponse.SC_NOT_FOUND);
+            }
+        } catch (SQLException ex) {
+            LOG.error("Database exception (Code {}): {}", ex.getErrorCode(), ex.getMessage());
+            LOG.debug("Details: ", ex);
+            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Database Error - Code:" + ex.getErrorCode());
         }
     }
 
--- a/src/main/java/de/uapcore/lightpit/DatabaseFacade.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/DatabaseFacade.java	Mon May 11 19:09:06 2020 +0200
@@ -28,8 +28,6 @@
  */
 package de.uapcore.lightpit;
 
-import de.uapcore.lightpit.dao.DataAccessObjects;
-import de.uapcore.lightpit.dao.postgres.PGDataAccessObjects;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -91,29 +89,14 @@
 
     private static final String DS_JNDI_NAME = "jdbc/lightpit/app";
     private DataSource dataSource;
-    private DataAccessObjects dataAccessObjects;
 
     /**
      * Returns the data source.
-     * <p>
-     * The Optional returned should never be empty. However, if something goes
-     * wrong during initialization, the data source might be absent.
-     * Hence, users of this data source are forced to check the existence.
      *
      * @return a data source
      */
-    public Optional<DataSource> getDataSource() {
-        // TODO: this should not be an optional, if an empty optional is actually an exception
-        return Optional.ofNullable(dataSource);
-    }
-
-    /**
-     * Returns the data access objects.
-     *
-     * @return an interface to obtain the data access objects
-     */
-    public DataAccessObjects getDataAccessObjects() {
-        return dataAccessObjects;
+    public DataSource getDataSource() {
+        return dataSource;
     }
 
     public Dialect getSQLDialect() {
@@ -171,8 +154,6 @@
             }
         }
 
-        dataAccessObjects = createDataAccessObjects(dialect);
-
         try {
             LOG.debug("Trying to access JNDI context {}...", contextName);
             Context initialCtx = new InitialContext();
@@ -191,15 +172,6 @@
         LOG.info("Database facade injected into ServletContext.");
     }
 
-    private static DataAccessObjects createDataAccessObjects(Dialect dialect) {
-        switch (dialect) {
-            case Postgres:
-                return new PGDataAccessObjects();
-            default:
-                throw new AssertionError("Non-exhaustive switch - this is a bug.");
-        }
-    }
-
     @Override
     public void contextDestroyed(ServletContextEvent sce) {
         dataSource = null;
--- a/src/main/java/de/uapcore/lightpit/dao/AbstractDao.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/AbstractDao.java	Mon May 11 19:09:06 2020 +0200
@@ -28,24 +28,65 @@
  */
 package de.uapcore.lightpit.dao;
 
-import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
 
 public abstract class AbstractDao<T> implements GenericDao<T> {
 
-    protected abstract PreparedStatement listQuery(Connection connection) throws SQLException;
+    private final PreparedStatement listQuery;
+
+    protected AbstractDao(PreparedStatement listQuery) {
+        this.listQuery = listQuery;
+    }
+
+    public final T mapColumns(ResultSet result) throws SQLException {
+        return mapColumns(result, "");
+    }
+
+    public abstract T mapColumns(ResultSet result, String qualifier) throws SQLException;
 
-    protected abstract T mapColumns(ResultSet result) throws SQLException;
+    /**
+     * Qualifies a column label if an qualifier is specified.
+     *
+     * @param qualifier an optional qualifier
+     * @param label     the column label
+     * @return the label, qualified if necessary
+     */
+    protected final String qual(String qualifier, String label) {
+        if (qualifier == null || qualifier.isBlank()) {
+            return label;
+        } else {
+            return qualifier + "." + label;
+        }
+    }
+
+    protected final void setStringOrNull(PreparedStatement stmt, int index, String str) throws SQLException {
+        if (str == null || str.isBlank()) {
+            stmt.setNull(index, Types.VARCHAR);
+        } else {
+            stmt.setString(index, str);
+        }
+    }
+
+    protected final <T> void setForeignKeyOrNull(PreparedStatement stmt, int index, T instance, Function<T, Integer> keyGetter) throws SQLException {
+        Integer key = Optional.ofNullable(instance).map(keyGetter).orElse(null);
+        if (key == null) {
+            stmt.setNull(index, Types.INTEGER);
+        } else {
+            stmt.setInt(index, key);
+        }
+    }
 
     @Override
-    public List<T> list(Connection conn) throws SQLException {
+    public List<T> list() throws SQLException {
         List<T> list = new ArrayList<>();
-        try (PreparedStatement stmt = listQuery(conn);
-             ResultSet result = stmt.executeQuery()) {
+        try (ResultSet result = listQuery.executeQuery()) {
             while (result.next()) {
                 list.add(mapColumns(result));
             }
--- a/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java	Mon May 11 19:09:06 2020 +0200
@@ -30,4 +30,6 @@
 
 public interface DataAccessObjects {
     UserDao getUserDao();
+
+    ProjectDao getProjectDao();
 }
--- a/src/main/java/de/uapcore/lightpit/dao/GenericDao.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/GenericDao.java	Mon May 11 19:09:06 2020 +0200
@@ -28,7 +28,6 @@
  */
 package de.uapcore.lightpit.dao;
 
-import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.List;
 
@@ -36,9 +35,38 @@
     /**
      * Returns a list of all entities.
      *
-     * @param connection conn the connection to use
      * @return a list of all objects
      * @throws SQLException on any kind of SQL errors
      */
-    List<T> list(Connection connection) throws SQLException;
+    List<T> list() throws SQLException;
+
+    /**
+     * Inserts an instance into database.
+     *
+     * @param instance the instance to insert
+     * @throws SQLException on any kind of SQL errors
+     */
+    void save(T instance) throws SQLException;
+
+    /**
+     * Updates an instance in the database.
+     *
+     * @param instance the instance to insert
+     * @return true if an instance has been updated, false if no instance with the specified ID was found
+     * @throws SQLException on any kind of SQL errors
+     */
+    boolean update(T instance) throws SQLException;
+
+    /**
+     * Inserts or updates an instance in the database.
+     * Tries an update first and if that fails, performs a save.
+     *
+     * @param instance the instance to insert or update
+     * @throws SQLException on any kind of SQL errors
+     * @see #update(Object)
+     * @see #save(Object)
+     */
+    default void saveOrUpdate(T instance) throws SQLException {
+        if (!update(instance)) save(instance);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/dao/ProjectDao.java	Mon May 11 19:09:06 2020 +0200
@@ -0,0 +1,34 @@
+/*
+ * 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.Project;
+
+public interface ProjectDao extends GenericDao<Project> {
+}
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java	Mon May 11 19:09:06 2020 +0200
@@ -29,14 +29,30 @@
 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 java.sql.Connection;
+import java.sql.SQLException;
+
 public class PGDataAccessObjects implements DataAccessObjects {
 
-    private final UserDao userDao = new PGUserDao();
+    private final UserDao userDao;
+    private final ProjectDao projectDao;
+
+    public PGDataAccessObjects(Connection connection) throws SQLException {
+        final PGUserDao pgUserDao = new PGUserDao(connection);
+        userDao = pgUserDao;
+        projectDao = new PGProjectDao(connection, pgUserDao);
+    }
 
     @Override
     public UserDao getUserDao() {
         return userDao;
     }
+
+    @Override
+    public ProjectDao getProjectDao() {
+        return projectDao;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java	Mon May 11 19:09:06 2020 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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.AbstractDao;
+import de.uapcore.lightpit.dao.ProjectDao;
+import de.uapcore.lightpit.entities.Project;
+import de.uapcore.lightpit.entities.User;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Objects;
+
+public final class PGProjectDao extends AbstractDao<Project> implements ProjectDao {
+
+    private final PGUserDao userDao;
+
+    private final PreparedStatement insert;
+    private final PreparedStatement update;
+
+    public PGProjectDao(Connection connection, PGUserDao userDao) throws SQLException {
+        super(connection.prepareStatement(
+                "select * from lpit_project join lpit_user owner on lpit_project.owner = owner.userid"));
+
+        insert = connection.prepareStatement(
+                "insert into lpit_project (name, description, repourl, owner) values (?, ?, ?, ?)"
+        );
+        update = connection.prepareStatement(
+                "update lpit_project set name = ?, description = ?, repourl = ?, owner = ? where id = ?"
+        );
+
+        this.userDao = userDao;
+    }
+
+    @Override
+    public Project mapColumns(ResultSet result, String q) throws SQLException {
+        final var proj = new Project(result.getInt(qual(q, "id")));
+        proj.setName(result.getString(qual(q, "name")));
+        proj.setDescription(result.getString(qual(q, "description")));
+        proj.setRepoUrl(result.getString(qual(q, "repourl")));
+        proj.setOwner(userDao.mapColumns(result, "owner"));
+        return proj;
+    }
+
+    @Override
+    public void save(Project instance) throws SQLException {
+        Objects.requireNonNull(instance.getName());
+        insert.setString(1, instance.getName());
+        setStringOrNull(insert, 2, instance.getDescription());
+        setStringOrNull(insert, 3, instance.getRepoUrl());
+        setForeignKeyOrNull(insert, 4, instance.getOwner(), User::getUserID);
+        insert.executeUpdate();
+    }
+
+    @Override
+    public boolean update(Project instance) throws SQLException {
+        Objects.requireNonNull(instance.getName());
+        update.setString(1, instance.getName());
+        setStringOrNull(update, 2, instance.getDescription());
+        setStringOrNull(update, 3, instance.getRepoUrl());
+        setForeignKeyOrNull(update, 4, instance.getOwner(), User::getUserID);
+        return update.executeUpdate() > 0;
+    }
+}
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java	Mon May 11 19:09:06 2020 +0200
@@ -36,20 +36,45 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Objects;
 
 public final class PGUserDao extends AbstractDao<User> implements UserDao {
 
+    private final PreparedStatement insert;
+    private final PreparedStatement update;
+
+    public PGUserDao(Connection connection) throws SQLException {
+        super(connection.prepareStatement("select * from lpit_user where userid >= 0 order by username"));
+
+        insert = connection.prepareStatement("insert into lpit_user (username, lastname, givenname, mail) values (?, ?, ?, ?)");
+        update = connection.prepareStatement("update lpit_user set lastname = ?, givenname = ?, mail = ? where userid = ?");
+    }
+
     @Override
-    protected User mapColumns(ResultSet result) throws SQLException {
-        final var user = new User(result.getInt("userid"));
-        user.setUsername(result.getString("username"));
-        user.setGivenname(result.getString("givenname"));
-        user.setLastname(result.getString("lastname"));
+    public User mapColumns(ResultSet result, String q) throws SQLException {
+        final var user = new User(result.getInt(qual(q, "userid")));
+        user.setUsername(result.getString(qual(q, "username")));
+        user.setGivenname(result.getString(qual(q, "givenname")));
+        user.setLastname(result.getString(qual(q, "lastname")));
         return user;
     }
 
     @Override
-    protected PreparedStatement listQuery(Connection conn) throws SQLException {
-        return conn.prepareStatement("select * from lpit_user where userid >= 0 order by username");
+    public void save(User instance) throws SQLException {
+        Objects.requireNonNull(instance.getUsername());
+        insert.setString(1, instance.getUsername());
+        setStringOrNull(insert, 2, instance.getLastname());
+        setStringOrNull(insert, 3, instance.getGivenname());
+        setStringOrNull(insert, 4, instance.getMail());
+        insert.executeUpdate();
+    }
+
+    @Override
+    public boolean update(User instance) throws SQLException {
+        setStringOrNull(update, 1, instance.getLastname());
+        setStringOrNull(update, 2, instance.getGivenname());
+        setStringOrNull(update, 3, instance.getMail());
+        update.setInt(4, instance.getUserID());
+        return update.executeUpdate() > 0;
     }
 }
--- a/src/main/java/de/uapcore/lightpit/entities/Project.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/entities/Project.java	Mon May 11 19:09:06 2020 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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.util.ArrayList;
--- a/src/main/java/de/uapcore/lightpit/entities/Version.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/entities/Version.java	Mon May 11 19:09:06 2020 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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.util.Objects;
--- a/src/main/java/de/uapcore/lightpit/entities/VersionStatus.java	Sun May 10 10:58:31 2020 +0200
+++ b/src/main/java/de/uapcore/lightpit/entities/VersionStatus.java	Mon May 11 19:09:06 2020 +0200
@@ -1,3 +1,31 @@
+/*
+ * 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 VersionStatus {

mercurial