/* © SRSoftware 2025 */ package de.srsoftware.umbrella.message; import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Query.*; import static de.srsoftware.umbrella.core.Errors.*; import static de.srsoftware.umbrella.core.constants.Constants.TABLE_SETTINGS; import static de.srsoftware.umbrella.core.constants.Field.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.model.Translatable.t; import static de.srsoftware.umbrella.message.model.Schedule.schedule; import static java.text.MessageFormat.format; import de.srsoftware.umbrella.core.constants.Text; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.UmbrellaUser; import de.srsoftware.umbrella.message.model.Instantly; import de.srsoftware.umbrella.message.model.Settings; import de.srsoftware.umbrella.message.model.Silent; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Arrays; public class SqliteMessageDb implements MessageDb{ private static final System.Logger LOG = System.getLogger(SqliteMessageDb.class.getSimpleName()); private final Connection db; private static final String DB_VERSION = "message_db_version"; private static final int INITIAL_DB_VERSION = 1; private static final String TABLE_SUBMISSIONS = "message_submission"; public SqliteMessageDb(Connection conn){ db = conn; init(); } private void createSubmissionTable() { var createTable = """ CREATE TABLE IF NOT EXISTS {0} ( {1} Integer PRIMARY KEY, {2} VARCHAR(255) NOT NULL); """; try { var stmt = db.prepareStatement(format(createTable,TABLE_SUBMISSIONS, USER_ID, VALUE)); stmt.execute(); stmt.close(); } catch (SQLException e) { throw failedToCreateTable(TABLE_SUBMISSIONS).causedBy(e); } } private int createSettingsTable() { var createTable = """ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255) NOT NULL); """; try { var stmt = db.prepareStatement(format(createTable,TABLE_SETTINGS, KEY, VALUE)); stmt.execute(); stmt.close(); } catch (SQLException e) { throw failedToCreateTable(TABLE_SETTINGS).causedBy(e); } Integer version = null; try { var rs = select(VALUE).from(TABLE_SETTINGS).where(KEY, equal(DB_VERSION)).exec(db); if (rs.next()) version = rs.getInt(VALUE); rs.close(); if (version == null) { version = INITIAL_DB_VERSION; insertInto(TABLE_SETTINGS, KEY, VALUE).values(DB_VERSION,version).execute(db).close(); } return version; } catch (SQLException e) { throw databaseException(FAILED_TO_UPDATE_OBJECT, OBJECT,DB_VERSION).causedBy(e); } } private int createTables() { createSubmissionTable(); return createSettingsTable(); } @Override public Settings getSettings(UmbrellaUser user) throws UmbrellaException { try { Settings settings = null; var rs = select(VALUE).from(TABLE_SUBMISSIONS).where(USER_ID,equal(user.id())).exec(db); if (rs.next()) settings = toSettings(rs); rs.close(); if (settings != null) return settings; throw new UmbrellaException(500,"No submission settings stored for {0}",user); } catch (SQLException e) { throw databaseException(FAILED_TO_LOAD_ENTITIES_OF_OWNER, TYPE,t(Text.SETTINGS), OWNER,user).causedBy(e); } } private void init() { var version = createTables(); } private Settings toSettings(ResultSet rs) throws SQLException { var submission = rs.getString(VALUE); if (submission.trim().equalsIgnoreCase(INSTANTLY)) return new Instantly(); try { var times = Arrays.stream(submission.split(",")).map(Integer::parseInt).toList(); return schedule(times); } catch (NumberFormatException nfe){ return new Silent(); } } @Override public Settings update(UmbrellaUser user, Settings settings) throws UmbrellaException { try { replaceInto(TABLE_SUBMISSIONS, USER_ID, VALUE).values(user.id(),settings.toString()).execute(db).close(); return settings; } catch (SQLException e) { throw failedToStoreObject("submission data").causedBy(e); } } }