SQLite support - work in progress

This commit is contained in:
Robert Vokac 2024-03-09 20:31:52 +00:00
parent e43df2feca
commit 48bac8b5f5
No known key found for this signature in database
GPG Key ID: 693D30BEE3329055
14 changed files with 340 additions and 17 deletions

View File

@ -1,5 +1,6 @@
package org.nanoboot.utils.timecalc.app;
import java.io.File;
import org.nanoboot.utils.timecalc.entity.Visibility;
import org.nanoboot.utils.timecalc.swing.common.MainWindow;
import org.nanoboot.utils.timecalc.utils.common.Constants;
@ -9,6 +10,14 @@ import org.nanoboot.utils.timecalc.utils.property.StringProperty;
import javax.swing.JOptionPane;
import java.io.IOException;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.nanoboot.utils.timecalc.persistence.api.VersionRepositoryApi;
import org.nanoboot.utils.timecalc.persistence.impl.sqlite.SqliteConnectionFactory;
import org.nanoboot.utils.timecalc.persistence.impl.sqlite.VersionRepositorySQLiteImpl;
/**
* @author Robert Vokac
@ -29,6 +38,11 @@ public class TimeCalcApp {
if (!FileConstants.TC_DIRECTORY.exists()) {
FileConstants.TC_DIRECTORY.mkdir();
}
try {
initDB();
} catch(Exception e) {
e.printStackTrace();
}
while (true) {
boolean test = FileConstants.TEST_TXT.exists();
String oldStartTime = Utils.readTextFromFile(
@ -99,4 +113,54 @@ public class TimeCalcApp {
return System.nanoTime() - startNanoTime;
}
private void initDB() {
SqliteConnectionFactory sqliteConnectionFactory = new SqliteConnectionFactory();
try {
Connection conn = sqliteConnectionFactory.createConnection();
} catch (ClassNotFoundException ex) {
Logger.getLogger(TimeCalcApp.class.getName()).log(Level.SEVERE, null, ex);
throw new TimeCalcException(ex);
}
List<String> files;
try {
files = Utils.loadFilesFromJarResources(DB_MIGRATIONSQLITETIMECALC, getClass());
} catch (IOException ex) {
Logger.getLogger(TimeCalcApp.class.getName()).log(Level.SEVERE, null, ex);
throw new TimeCalcException(ex);
}
Collections.sort(files);
int lastVersion = 0;
VersionRepositoryApi versionRepository = new VersionRepositorySQLiteImpl(sqliteConnectionFactory);
int currentVersion = 0;
try {
currentVersion = versionRepository.read();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("currentVersion=" + currentVersion);
for(String sql :files) {
Integer version = Integer.valueOf(sql.split("__")[0].substring(1));
lastVersion = version;
System.out.println("version=" + version);
if(currentVersion >= version) {
continue;
}
try {
System.out.println("Reading this file: " + DB_MIGRATIONSQLITETIMECALC + "/" + sql);
String text = Utils.readTextFromTextResourceInJar(DB_MIGRATIONSQLITETIMECALC + "/" + sql);
System.out.println("Found sql: \n\n" + text);
sqliteConnectionFactory.runSQL(text);
} catch (IOException ex) {
Logger.getLogger(TimeCalcApp.class.getName()).log(Level.SEVERE, null, ex);
throw new TimeCalcException(ex);
}
}
if(currentVersion != lastVersion) {
versionRepository.update(lastVersion);
}
}
private static final String DB_MIGRATIONSQLITETIMECALC = "db_migrations/sqlite/timecalc";
}

View File

@ -1,5 +1,7 @@
package org.nanoboot.utils.timecalc.app;
import org.nanoboot.utils.timecalc.utils.common.Utils;
/**
* @author Robert Vokac
* @since 21.02.2024
@ -8,9 +10,11 @@ public class TimeCalcException extends RuntimeException {
public TimeCalcException(String msg) {
super(msg);
Utils.showNotification("Error happened: " + msg);
}
public TimeCalcException(Exception e) {
super(e);
Utils.showNotification("Error happened: " + e.getMessage());
}
}

View File

@ -22,7 +22,6 @@ public class WorkingDay {
private int overtimeHour;
private int overtimeMinute;
private boolean halfDay;
private int workingTimeInMinutes;
private int pauseTimeInMinutes;
private String note;

View File

@ -0,0 +1,13 @@
package org.nanoboot.utils.timecalc.persistence.api;
/**
* @author Robert Vokac
* @since 23.02.2024
*/
public interface VersionRepositoryApi {
int read();
void update(int newVersion);
}

View File

@ -23,7 +23,9 @@ import org.nanoboot.utils.timecalc.utils.common.FileConstants;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.nanoboot.utils.timecalc.app.TimeCalcException;
/**
*
@ -34,14 +36,14 @@ public class SqliteConnectionFactory implements ConnectionFactory {
private final String jdbcUrl;
private static String createJdbcUrl(String directoryWhereSqliteFileIs) {
return "jdbc:sqlite:" + directoryWhereSqliteFileIs + "/" + ".time-calc.sqlite3?foreign_keys=on;";
return "jdbc:sqlite:" + directoryWhereSqliteFileIs + "/" + "time-calc.sqlite3?foreign_keys=on;";
}
public SqliteConnectionFactory() {
this(FileConstants.TC_DIRECTORY.getName());
}
public SqliteConnectionFactory(String directoryWhereSqliteFileIs) {
private SqliteConnectionFactory(String directoryWhereSqliteFileIs) {
this.jdbcUrl = createJdbcUrl(directoryWhereSqliteFileIs);
}
@ -61,5 +63,29 @@ public class SqliteConnectionFactory implements ConnectionFactory {
return null;
}
}
public void runSQL(String sql) {
String[] array = sql.split(";");
for (String s : array) {
if (s.trim().isEmpty()) {
continue;
}
System.err.println("Going to run this SQL \"" + s + "\"");
try (
Connection connection = createConnection(); PreparedStatement stmt = connection.prepareStatement(s);) {
System.err.println(stmt.toString());
stmt.execute();
} catch (SQLException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
throw new TimeCalcException(ex);
}
}
}
}

View File

@ -0,0 +1,83 @@
package org.nanoboot.utils.timecalc.persistence.impl.sqlite;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.nanoboot.utils.timecalc.app.TimeCalcException;
import org.nanoboot.utils.timecalc.persistence.api.VersionRepositoryApi;
/**
* @author Robert Vokac
* @since 23.02.2024
*/
public class VersionRepositorySQLiteImpl implements VersionRepositoryApi {
private final SqliteConnectionFactory sqliteConnectionFactory;
public VersionRepositorySQLiteImpl(SqliteConnectionFactory sqliteConnectionFactory) {
this.sqliteConnectionFactory = sqliteConnectionFactory;
}
@Override
public int read() {
StringBuilder sb = new StringBuilder();
sb
.append("SELECT * FROM ")
.append(VersionTable.TABLE_NAME);
String sql = sb.toString();
// System.err.println(sql);
ResultSet rs = null;
try (
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
System.err.println(stmt.toString());
rs = stmt.executeQuery();
while (rs.next()) {
return rs.getInt(VersionTable.VALUE);
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
} finally {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
throw new TimeCalcException("Version was not found in database.");
}
@Override
public void update(int newVersion) {
StringBuilder sb = new StringBuilder();
sb
.append("UPDATE ")
.append(VersionTable.TABLE_NAME)
.append(" SET ")
.append(VersionTable.VALUE).append("=").append(newVersion);
String sql = sb.toString();
//System.err.println(sql);
try (
Connection connection = sqliteConnectionFactory.createConnection(); PreparedStatement stmt = connection.prepareStatement(sql);) {
int numberOfUpdatedRows = stmt.executeUpdate();
System.out.println("numberOfUpdatedRows=" + numberOfUpdatedRows);
} catch (SQLException e) {
System.out.println(e.getMessage());
throw new RuntimeException(e);
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,35 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// bit-inspector: Tool detecting bit rots in files.
// Copyright (C) 2023-2023 the original author or authors.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2
// of the License only.
//
// 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
///////////////////////////////////////////////////////////////////////////////////////////////
package org.nanoboot.utils.timecalc.persistence.impl.sqlite;
/**
*
* @author <a href="mailto:robertvokac@nanoboot.org">Robert Vokac</a>
*/
class VersionTable {
public static final String TABLE_NAME = "VERSION";
public static final String VALUE = "VALUE";
private VersionTable() {
//Not meant to be instantiated.
}
}

View File

@ -33,9 +33,7 @@ class WorkingDayTable {
public static final String ARRIVAL_HOUR = "ARRIVAL_HOUR";
public static final String ARRIVAL_MINUTE = "ARRIVAL_MINUTE";
public static final String HALF_DAY = "HALF_DAY";
public static final String OVERTIME_HOUR = "OVERTIME_HOUR";
public static final String OVERTIME_MINUTE = "OVERTIME_MINUTE";
public static final String WORKING_TIME_IN_MINUTES = "WORKING_TIME_IN_MINUTES";
public static final String PAUSE_TIME_IN_MINUTES = "PAUSE_TIME_IN_MINUTES";

View File

@ -696,6 +696,9 @@ public class MainWindow extends TWindow {
TTime nowTime = TTime.of(time.asCalendar());
TTime timeElapsed = TTime
.computeTimeDiff(startTime, nowTime);
System.out.println("timeElapsed=" + timeElapsed.toString());
System.out.println("startTime=" + startTime.toString());
System.out.println("nowTime=" + nowTime.toString());
TTime timeRemains = TTime.computeTimeDiff(nowTime, endTime);
TTime timeTotal = TTime.computeTimeDiff(startTime, endTime);
String timeElapsedString = timeElapsed.toString();
@ -724,8 +727,12 @@ public class MainWindow extends TWindow {
int totalMilliseconds = timeTotal.toTotalMilliseconds();
int totalMinutes = totalMilliseconds / 1000 / 60 ;
System.out.println("totalMillisecondsDone=" + totalMillisecondsDone);
System.out.println("totalMilliseconds=" + totalMilliseconds);
double done = ((double) totalMillisecondsDone)
/ ((double) totalMilliseconds);
if(done == 1)
System.out.println("a");
if (done < 0) {
done = 0;
}
@ -788,8 +795,7 @@ public class MainWindow extends TWindow {
}
}
} else {
walkingHumanProgress
.setDonePercent(done);
walkingHumanProgress.setDonePercent(done);
}
try {

View File

@ -66,15 +66,22 @@ public class Time extends Thread {
public Calendar asCalendar() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, yearProperty.getValue());
cal.set(Calendar.MONTH, monthProperty.getValue() - 1);
cal.set(Calendar.DAY_OF_MONTH, dayProperty.getValue());
cal.set(Calendar.HOUR_OF_DAY, hourProperty.getValue());
cal.set(Calendar.MINUTE, minuteProperty.getValue());
cal.set(Calendar.SECOND, secondProperty.getValue());
cal.set(Calendar.MILLISECOND, millisecondProperty.getValue());
cal.set(Calendar.YEAR, returnValueAsNeeded(yearProperty, yearCustomProperty));
cal.set(Calendar.MONTH, returnValueAsNeeded(monthProperty, monthCustomProperty) - 1);
cal.set(Calendar.DAY_OF_MONTH, returnValueAsNeeded(dayProperty, dayCustomProperty));
cal.set(Calendar.HOUR_OF_DAY, returnValueAsNeeded(hourProperty, hourCustomProperty));
cal.set(Calendar.MINUTE, returnValueAsNeeded(minuteProperty, minuteCustomProperty));
cal.set(Calendar.SECOND, returnValueAsNeeded(secondProperty, secondCustomProperty));
cal.set(Calendar.MILLISECOND, returnValueAsNeeded(millisecondProperty, millisecondCustomProperty));
return cal;
}
private int returnValueAsNeeded(ReadOnlyProperty<Integer> p1, IntegerProperty p2) {
return returnValueAsNeeded(p1.getValue(), p2.getValue());
}
private int returnValueAsNeeded(int i1, int i2) {
return i2 == Integer.MAX_VALUE ? i1 : i2;
}
public void run() {

View File

@ -17,8 +17,6 @@ import javax.swing.Timer;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.HashSet;
@ -102,6 +100,8 @@ public class WalkingHumanProgress extends Widget implements
StringBuilder sb = new StringBuilder();
final int donePercentInt = (int) (Math.floor(donePercent * 100));
System.out.println("donePercent=" + donePercent);
System.out.println("donePercentInt=" + donePercentInt);
int percentInt = donePercentInt;
if (donePercentInt % 5 == 0 && !alreadyShownPercents.contains(donePercentInt)) {

View File

@ -10,12 +10,24 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import org.nanoboot.utils.timecalc.app.TimeCalcException;
/**
* @author Robert Vokac
@ -124,7 +136,55 @@ public class Utils {
return base64Decoder
.decode(s.getBytes());
}
public static List<String> loadFilesFromJarResources(String p, Class<?> clazz) throws IOException {
List<String> result = new ArrayList<>();
try {
List<Path> paths = getPathsFromResourceJar(p, clazz);
for (Path path : paths) {
System.out.println("Path : " + path);
String filePathInJAR = path.toString();
if (filePathInJAR.startsWith("/")) {
filePathInJAR = filePathInJAR.substring(1, filePathInJAR.length());
}
System.out.println("filePathInJAR : " + filePathInJAR);
String[] array = filePathInJAR.split("/");
result.add(array[array.length - 1]);
}
} catch (URISyntaxException | IOException e) {
System.err.println(e.getMessage());
e.printStackTrace();
throw new TimeCalcException(e);
}
return result;
}
private static List<Path> getPathsFromResourceJar(String folder, Class<?> clazz)
throws URISyntaxException, IOException {
List<Path> result;
String jarPath = clazz.getProtectionDomain()
.getCodeSource()
.getLocation()
.toURI()
.getPath();
System.out.println("JAR Path : " + jarPath);
URI uri = URI.create("jar:file:" + jarPath);
try ( FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap());Stream<Path> stream = Files.walk(fs.getPath(folder))) {
result = stream
.filter(Files::isRegularFile)
.toList();
}
return result;
}
public static String readTextFromTextResourceInJar(String pathToFile)
throws IOException {
InputStream inputStream = ClassLoader.getSystemClassLoader().
@ -139,7 +199,14 @@ public class Utils {
}
return sb.toString();
}
public static String loadStacktrace(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return sw.toString();
}
public static void showNotification(String message) {
showNotification(message, 0);
}

View File

@ -0,0 +1,4 @@
CREATE TABLE "VERSION" (
"VALUE" NUMBER
);
INSERT INTO VERSION VALUES ("1");

View File

@ -0,0 +1,17 @@
CREATE TABLE "WORKING_DAY" (
"ID" TEXT,
"YEAR" NUMBER NOT NULL,
"MONTH" NUMBER NOT NULL,
"DAY" NUMBER NOT NULL,
--
"ARRIVAL_HOUR" NUMBER NOT NULL,
"ARRIVAL_MINUTE" NUMBER NOT NULL,
"OVERTIME_HOUR" NUMBER NOT NULL,
"OVERTIME_MINUTE" NUMBER NOT NULL,
--
"WORKING_TIME_IN_MINUTES" NUMBER NOT NULL,
"PAUSE_TIME_IN_MINUTES" NUMBER NOT NULL,
--
"NOTE" TEXT NOT NULL,
PRIMARY KEY("ID")
);