Mon, 11 May 2020 19:09:06 +0200
adds DAO for Project entity and save/update methods
--- 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 {