Java tutorial
/* * Copyright (C) 2014-2015 ULYSSIS VZW * * This file is part of i++. * * i++ is free software: you can redistribute it and/or modify * it under the terms of version 3 of the GNU Affero General Public License * as published by the Free Software Foundation. No other versions apply. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> */ package org.ulyssis.ipp.snapshot; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.ulyssis.ipp.updates.Status; import org.ulyssis.ipp.utils.Serialization; import java.io.IOException; import java.sql.*; import java.time.Instant; import java.util.Optional; public final class Snapshot { private static final Logger LOG = LogManager.getLogger(Snapshot.class); public static class Builder { private Snapshot snapshot; private Builder(Instant time, Snapshot other) { snapshot = new Snapshot(time); if (other != null) { snapshot.teamTagMap = other.teamTagMap; snapshot.startTime = other.startTime; snapshot.endTime = other.endTime; snapshot.teamStates = other.teamStates; snapshot.publicTeamStates = other.publicTeamStates; snapshot.statusMessage = other.statusMessage; snapshot.status = other.status; snapshot.updateFrequency = other.updateFrequency; } } public Builder withTeamTagMap(TeamTagMap teamTagMap) { this.snapshot.teamTagMap = teamTagMap; return this; } public Builder withStartTime(Instant time) { this.snapshot.startTime = time; return this; } public Builder withEndTime(Instant time) { this.snapshot.endTime = time; return this; } public Builder withTeamStates(TeamStates teamStates) { this.snapshot.teamStates = teamStates; return this; } public Builder withPublicTeamStates(TeamStates teamStates) { this.snapshot.publicTeamStates = teamStates; return this; } public Builder withStatusMessage(String message) { this.snapshot.statusMessage = message; return this; } public Builder withStatus(Status status) { this.snapshot.status = status; return this; } public Builder withUpdateFrequency(int updateFrequency) { this.snapshot.updateFrequency = updateFrequency; return this; } public Snapshot build() { return snapshot; } } @JsonIgnore private long id = -1; @JsonIgnore long eventId = -1; public Optional<Long> getId() { if (id != -1) return Optional.of(id); else return Optional.empty(); } public Optional<Long> getEventId() { if (eventId != -1) return Optional.of(eventId); else return Optional.empty(); } /** * Default constructor for Jackson */ @SuppressWarnings("unused") private Snapshot() { } public Snapshot(Instant time) { snapshotTime = time; } public Instant getSnapshotTime() { return snapshotTime; } public TeamTagMap getTeamTagMap() { return teamTagMap; } public Instant getStartTime() { return startTime; } public Instant getEndTime() { return endTime; } public TeamStates getTeamStates() { return teamStates; } public TeamStates getPublicTeamStates() { return publicTeamStates; } public String getStatusMessage() { return statusMessage; } public Status getStatus() { return status; } public int getUpdateFrequency() { return updateFrequency; } private Instant snapshotTime = Instant.MIN; private Instant startTime = Instant.MAX; private Instant endTime = Instant.MAX; private TeamTagMap teamTagMap = new TeamTagMap(); private TeamStates teamStates; private TeamStates publicTeamStates; { teamStates = new TeamStates(); publicTeamStates = teamStates; } private String statusMessage = ""; private Status status = Status.NoResults; private int updateFrequency = 3; public static Builder builder(Instant time, Snapshot other) { return new Builder(time, other); } public static Optional<Snapshot> loadForEvent(Connection connection, Event event) throws SQLException, IOException { String statement = "SELECT \"id\", \"data\" FROM \"snapshots\" WHERE \"event\" = ?"; try (PreparedStatement stmt = connection.prepareStatement(statement)) { stmt.setLong(1, event.getId().get()); LOG.debug("executing query: {}", stmt); ResultSet rs = stmt.executeQuery(); if (rs.next()) { String data = rs.getString("data"); Snapshot result = Serialization.getJsonMapper().readValue(data, Snapshot.class); result.id = rs.getLong("id"); result.eventId = event.getId().get(); return Optional.of(result); } else { return Optional.empty(); } } } public static Optional<Snapshot> loadLatest(Connection connection) throws SQLException, IOException { String statement = "SELECT \"id\", \"data\", \"event\" FROM \"snapshots\" ORDER BY \"time\" DESC FETCH FIRST ROW ONLY"; try (Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(statement)) { if (rs.next()) { String data = rs.getString("data"); Snapshot result = Serialization.getJsonMapper().readValue(data, Snapshot.class); result.id = rs.getLong("id"); result.eventId = rs.getLong("event"); return Optional.of(result); } else { return Optional.empty(); } } } public static Optional<Snapshot> loadBefore(Connection connection, Instant time) throws SQLException, IOException { String statement = "SELECT \"id\", \"data\", \"event\" FROM \"snapshots\" " + "WHERE \"time\" < ? ORDER BY \"time\" DESC, \"event\" DESC FETCH FIRST ROW ONLY"; try (PreparedStatement stmt = connection.prepareStatement(statement)) { stmt.setTimestamp(1, Timestamp.from(time)); LOG.debug("Executing query: {}", stmt); ResultSet rs = stmt.executeQuery(); if (rs.next()) { String data = rs.getString("data"); Snapshot result = Serialization.getJsonMapper().readValue(data, Snapshot.class); result.id = rs.getLong("id"); result.eventId = rs.getLong("event"); return Optional.of(result); } else { return Optional.empty(); } } } public void save(Connection connection) throws SQLException { if (id != -1) return; try (PreparedStatement statement = connection.prepareStatement( "INSERT INTO \"snapshots\" (\"time\",\"data\",\"event\") VALUES (?,?,?)", Statement.RETURN_GENERATED_KEYS)) { statement.setTimestamp(1, Timestamp.from(snapshotTime)); String serialized; try { serialized = Serialization.getJsonMapper().writeValueAsString(this); } catch (JsonProcessingException e) { assert false; // TODO(Roel): Programming error return; } statement.setString(2, serialized); statement.setLong(3, eventId); statement.executeUpdate(); ResultSet keys = statement.getGeneratedKeys(); keys.next(); this.id = keys.getLong(1); } } public static void deleteAfter(Connection connection, Snapshot snapshot) throws SQLException { String statement = "DELETE FROM \"snapshots\" WHERE \"time\" > ? OR (\"time\" = ? AND \"event\" > ?)"; try (PreparedStatement stmt = connection.prepareStatement(statement)) { Timestamp timestamp = Timestamp.from(snapshot.getSnapshotTime()); stmt.setTimestamp(1, timestamp); stmt.setTimestamp(2, timestamp); stmt.setLong(3, snapshot.getEventId().orElse(-1L)); LOG.debug("Executing query: {}", stmt); int affectedRows = stmt.executeUpdate(); LOG.debug("deleteAfter affected {} rows", affectedRows); } } }