From c565660d31b1b0179c0f3edfb2b94a96bc37157d Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sat, 22 May 2021 22:23:41 +0200
Subject: [PATCH] #598 - upgrade database from one version to the next one
 until the latest version is reached

---
 .../budgetmaster/database/DatabaseParser.java | 41 +++++++++++++++----
 .../database/model/Upgradeable.java           |  6 +++
 2 files changed, 39 insertions(+), 8 deletions(-)
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java

diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java
index 5664f313a..4ecfce7d3 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java
@@ -2,8 +2,10 @@ package de.deadlocker8.budgetmaster.database;
 
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
-import de.deadlocker8.budgetmaster.database.legacy.LegacyParser;
 import de.deadlocker8.budgetmaster.categories.Category;
+import de.deadlocker8.budgetmaster.database.legacy.LegacyParser;
+import de.deadlocker8.budgetmaster.database.model.BackupDatabase;
+import de.deadlocker8.budgetmaster.database.model.v4.BackupDatabase_v4;
 import de.deadlocker8.budgetmaster.database.model.v5.BackupDatabase_v5;
 import de.thecodelabs.utils.util.Localization;
 import org.slf4j.Logger;
@@ -14,6 +16,9 @@ import java.text.MessageFormat;
 public class DatabaseParser
 {
 	final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+	private final int LATEST_VERSION = 5;
+
 	private final String jsonString;
 	private final Category categoryNone;
 
@@ -37,6 +42,8 @@ public class DatabaseParser
 			int version = root.get("VERSION").getAsInt();
 			LOGGER.info(MessageFormat.format("Parsing BudgetMaster database with version {0}", version));
 
+			BackupDatabase importedDatabase = null;
+
 			if(version == 2)
 			{
 				final Database database = new LegacyParser(jsonString, categoryNone).parseDatabaseFromJSON();
@@ -53,19 +60,24 @@ public class DatabaseParser
 
 			if(version == 4)
 			{
-				final Database database = new DatabaseParser_v4(jsonString).parseDatabaseFromJSON();
-				LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts and {3} templates", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplates().size()));
-				return database;
+				BackupDatabase_v4 parsedDatabase = new DatabaseParser_v4(jsonString).parseDatabaseFromJSON();
+				LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts and {3} templates", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size()));
+				importedDatabase = parsedDatabase;
 			}
 
 			if(version == 5)
 			{
-				final BackupDatabase_v5 database = new DatabaseParser_v5(jsonString).parseDatabaseFromJSON();
-				LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates and {4} charts", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplates().size(), database.getCharts().size()));
-				return database.convert();
+				BackupDatabase_v5 parsedDatabase = new DatabaseParser_v5(jsonString).parseDatabaseFromJSON();
+				LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates {4} charts and {5} images", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size(), parsedDatabase.getCharts().size(), parsedDatabase.getImages().size()));
+				importedDatabase = parsedDatabase;
 			}
 
-			throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version"));
+			if(importedDatabase == null)
+			{
+				throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version"));
+			}
+
+			return upgradeDatabase(importedDatabase);
 		}
 		catch(Exception e)
 		{
@@ -73,4 +85,17 @@ public class DatabaseParser
 			throw new IllegalArgumentException(Localization.getString("error.database.import.invalid.json"), e);
 		}
 	}
+
+	private Database upgradeDatabase(BackupDatabase importedDatabase)
+	{
+		BackupDatabase upgradedDatabase = importedDatabase;
+		while(upgradedDatabase.getVersion() < LATEST_VERSION)
+		{
+			LOGGER.debug(MessageFormat.format("Upgrading database from version {0} to {1}", upgradedDatabase.getVersion(), upgradedDatabase.getVersion() + 1));
+			upgradedDatabase = upgradedDatabase.upgrade();
+		}
+
+		LOGGER.debug(MessageFormat.format("Converting database with version {0} to internal entities", upgradedDatabase.getVersion()));
+		return upgradedDatabase.convert();
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java
new file mode 100644
index 000000000..4da81d206
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java
@@ -0,0 +1,6 @@
+package de.deadlocker8.budgetmaster.database.model;
+
+public interface Upgradeable<T>
+{
+	T upgrade();
+}
-- 
GitLab