diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java index 8d2b5a7f7..1cd48a1b7 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/CodeMigration.java @@ -18,6 +18,9 @@ package li.strolch.migrations; import java.io.File; import li.strolch.agent.api.ComponentContainer; +import li.strolch.command.parameter.SetParameterCommand; +import li.strolch.model.Resource; +import li.strolch.model.parameter.StringParameter; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.utils.Version; @@ -35,4 +38,15 @@ public class CodeMigration extends Migration { public void migrate(ComponentContainer container, Certificate certificate) { logger.info("[" + this.realm + "] Running no-op migration " + this.version); } + + @Override + protected void setNewVersion(SetParameterCommand cmd, Resource migrationsRes) { + StringParameter currentCodeVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION); + + cmd.setParameter(currentCodeVersionP); + cmd.setValueAsString(getVersion().toString()); + + } + + } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java index d4b7b6cf5..ae056e4d1 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/CurrentMigrationVersionQuery.java @@ -18,7 +18,8 @@ package li.strolch.migrations; import static li.strolch.migrations.Migration.BAG_PARAMETERS; import static li.strolch.migrations.Migration.MIGRATIONS_ID; import static li.strolch.migrations.Migration.MIGRATIONS_TYPE; -import static li.strolch.migrations.Migration.PARAM_CURRENT_VERSION; +import static li.strolch.migrations.Migration.PARAM_CURRENT_DATA_VERSION; +import static li.strolch.migrations.Migration.PARAM_CURRENT_CODE_VERSION; import java.util.HashMap; import java.util.Map; @@ -35,7 +36,7 @@ import ch.eitchnet.utils.Version; public class CurrentMigrationVersionQuery { private ComponentContainer container; - private Map currentVersions; + private Map currentVersions; /** * @param container @@ -55,29 +56,46 @@ public class CurrentMigrationVersionQuery { Resource migrationsRes = tx.getResourceBy(MIGRATIONS_TYPE, MIGRATIONS_ID); if (migrationsRes == null) { - this.currentVersions.put(realmName, Version.emptyVersion); + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion)); continue; } - StringParameter currentVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_VERSION); - if (currentVersionP == null) { - this.currentVersions.put(realmName, Version.emptyVersion); - continue; + StringParameter currentDataVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION); + StringParameter currentCodeVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION); + + if (currentDataVersionP == null && currentCodeVersionP == null) { + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion)); + } else if(currentDataVersionP == null && currentCodeVersionP != null) { + Version codeVersion = getVersionFromParam(currentCodeVersionP); + this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,codeVersion)); + } else if (currentDataVersionP != null && currentCodeVersionP == null) { + Version dataVersion = getVersionFromParam(currentDataVersionP); + this.currentVersions.put(realmName, new MigrationVersion(dataVersion,Version.emptyVersion)); + } else { + Version dataVersion = getVersionFromParam(currentDataVersionP); + Version codeVersion = getVersionFromParam(currentCodeVersionP); + this.currentVersions.put(realmName, new MigrationVersion(dataVersion,codeVersion)); } - - String versionS = currentVersionP.getValue(); - if (!Version.isParseable(versionS)) { - throw new StrolchConfigurationException("Version value " + versionS + " is not valid for " - + currentVersionP.getLocator()); - } - - Version version = Version.valueOf(versionS); - this.currentVersions.put(realmName, version); } } } - public Map getCurrentVersions() { + /** + * @param versionS + * @return + */ + private Version getVersionFromParam(StringParameter versionP) { + String versionS = versionP.getValue(); + if (!Version.isParseable(versionS)) { + throw new StrolchConfigurationException("Version value " + versionS + " is not valid for " + + versionP.getLocator()); + } + + Version version = Version.valueOf(versionS); + return version; + } + + public Map getCurrentVersions() { return this.currentVersions; } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java index d35aa4687..3bdea55d2 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/DataMigration.java @@ -21,8 +21,11 @@ import java.util.Collections; import li.strolch.agent.api.ComponentContainer; import li.strolch.command.XmlImportModelCommand; +import li.strolch.command.parameter.SetParameterCommand; import li.strolch.exception.StrolchException; import li.strolch.model.ModelStatistics; +import li.strolch.model.Resource; +import li.strolch.model.parameter.StringParameter; import li.strolch.persistence.api.StrolchTransaction; import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.utils.Version; @@ -60,4 +63,13 @@ public class DataMigration extends Migration { logger.info(MessageFormat .format("[{0}] Data migration for {1} loaded {2} Resources and {3} Orders.", getRealm(), getVersion(), statistics.nrOfResources, statistics.nrOfOrders)); //$NON-NLS-1$ } + + @Override + protected void setNewVersion(SetParameterCommand cmd, Resource migrationsRes) { + StringParameter currentDataVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION); + + cmd.setParameter(currentDataVersionP); + cmd.setValueAsString(getVersion().toString()); + } + } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java index 6a6ce71d0..d1ecb7878 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migration.java @@ -36,7 +36,8 @@ public abstract class Migration { public static final String MIGRATIONS_TYPE = "Migrations"; public static final String MIGRATIONS_ID = "migrations"; public static final String BAG_PARAMETERS = "parameters"; - public static final String PARAM_CURRENT_VERSION = "currentVersion"; + public static final String PARAM_CURRENT_DATA_VERSION = "currentDataVersion"; + public static final String PARAM_CURRENT_CODE_VERSION = "currentCodeVersion"; protected static final Logger logger = LoggerFactory.getLogger(CodeMigration.class); @@ -75,9 +76,13 @@ public abstract class Migration { ParameterBag bag = new ParameterBag(BAG_PARAMETERS, BAG_PARAMETERS, BAG_PARAMETERS); migrationsRes.addParameterBag(bag); - StringParameter currentVersionP = new StringParameter(PARAM_CURRENT_VERSION, PARAM_CURRENT_VERSION, - getVersion().toString()); - bag.addParameter(currentVersionP); + StringParameter currentDataVersionP = new StringParameter(PARAM_CURRENT_DATA_VERSION, + PARAM_CURRENT_DATA_VERSION, getVersion().toString()); + bag.addParameter(currentDataVersionP); + + StringParameter currentCodeVersionP = new StringParameter(PARAM_CURRENT_CODE_VERSION, + PARAM_CURRENT_CODE_VERSION, getVersion().toString()); + bag.addParameter(currentCodeVersionP); AddResourceCommand cmd = new AddResourceCommand(container, tx); cmd.setResource(migrationsRes); @@ -85,16 +90,15 @@ public abstract class Migration { tx.addCommand(cmd); } else { - - StringParameter currentVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_VERSION); - SetParameterCommand cmd = new SetParameterCommand(container, tx); - cmd.setParameter(currentVersionP); - cmd.setValueAsString(getVersion().toString()); + + setNewVersion(cmd,migrationsRes); tx.addCommand(cmd); } } public abstract void migrate(ComponentContainer container, Certificate certificate); + + protected abstract void setNewVersion(SetParameterCommand cmd,Resource migrationsRes); } diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java new file mode 100644 index 000000000..6ead4d919 --- /dev/null +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationVersion.java @@ -0,0 +1,37 @@ +/** + * + */ +package li.strolch.migrations; + +import ch.eitchnet.utils.Version; + +/** + * Migration versions for data and code migrations + * + * @author Reto Breitenmoser + */ +public class MigrationVersion { + + private Version dataVersion; + private Version codeVersion; + + public MigrationVersion(Version dataVersion, Version codeVersion) { + this.dataVersion = dataVersion; + this.codeVersion = codeVersion; + } + + /** + * @return the dataVersion + */ + public Version getDataVersion() { + return dataVersion; + } + + /** + * @return the codeVersion + */ + public Version getCodeVersion() { + return codeVersion; + } + +} diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java index d0f7811f8..184691b84 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/Migrations.java @@ -81,20 +81,21 @@ public class Migrations { logDetectedMigrations(this.realmNames, this.dataMigrations, this.codeMigrations); } - public void runMigrations(Certificate certificate, Map currentVersions) { + public void runMigrations(Certificate certificate, Map currentVersions) { MapOfLists migrationsRan = new MapOfLists<>(); - for (Entry entry : currentVersions.entrySet()) { + for (Entry entry : currentVersions.entrySet()) { String realm = entry.getKey(); - Version currentVersion = entry.getValue(); + MigrationVersion currentVersion = entry.getValue(); if (this.verbose) logger.info("[" + realm + "] Performing all migrations after " + currentVersion); - Version nextPossibleVersion = currentVersion.add(0, 0, 1); - CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null); - DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null); + Version nextPossibleCodeVersion = currentVersion.getCodeVersion().add(0, 0, 1); + Version nextPossibleDataVersion = currentVersion.getDataVersion().add(0, 0, 1); + CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleCodeVersion, null); + DataMigration currentDataMigration = new DataMigration(realm, nextPossibleDataVersion, null); SortedSet dataMigrations = this.dataMigrations.get(realm); if (dataMigrations != null && !dataMigrations.isEmpty()) { @@ -131,7 +132,7 @@ public class Migrations { * @param cert * @param codeMigrationsByRealm */ - public void runCodeMigrations(Certificate cert, Map currentVersions, + public void runCodeMigrations(Certificate cert, Map currentVersions, MapOfLists codeMigrationsByRealm) { MapOfLists migrationsRan = new MapOfLists<>(); @@ -142,21 +143,21 @@ public class Migrations { if (!this.realmNames.contains(realm)) continue; - Version currentVersion = currentVersions.get(realm); + MigrationVersion currentVersion = currentVersions.get(realm); List listOfMigrations = codeMigrationsByRealm.getList(realm); SortedSet migrations = new TreeSet<>((o1, o2) -> o1.getVersion().compareTo(o2.getVersion())); migrations.addAll(listOfMigrations); - Version nextVersion = currentVersion.add(0, 0, 1); + Version nextVersion = currentVersion.getCodeVersion().add(0, 0, 1); CodeMigration nextMigration = new CodeMigration(realm, nextVersion); SortedSet migrationsToRun = migrations.tailSet(nextMigration); for (CodeMigration migration : migrationsToRun) { DBC.INTERIM.assertEquals("Realms do not match!", realm, migration.getRealm()); Version migrateVersion = migration.getVersion(); - boolean isLaterMigration = migrateVersion.compareTo(currentVersion) > 0; - DBC.INTERIM.assertTrue("Current version " + currentVersion + " is not before next " + migrateVersion, + boolean isLaterMigration = migrateVersion.compareTo(currentVersion.getCodeVersion()) > 0; + DBC.INTERIM.assertTrue("Current version " + currentVersion.getCodeVersion() + " is not before next " + migrateVersion, isLaterMigration); String msg = "[{0}] Running code migration {1} {2}"; @@ -264,15 +265,16 @@ public class Migrations { return migrationsByRealm; } - public MapOfLists getMigrationsToRun(Map currentVersions) { + public MapOfLists getMigrationsToRun(Map currentVersions) { MapOfLists migrationsToRun = new MapOfLists<>(); - for (Entry entry : currentVersions.entrySet()) { + for (Entry entry : currentVersions.entrySet()) { String realm = entry.getKey(); - Version nextPossibleVersion = entry.getValue().add(0, 0, 1); - CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleVersion, null); - DataMigration currentDataMigration = new DataMigration(realm, nextPossibleVersion, null); + Version nextPossibleCodeVersion = entry.getValue().getCodeVersion().add(0, 0, 1); + Version nextPossibleDataVersion = entry.getValue().getDataVersion().add(0, 0, 1); + CodeMigration currentCodeMigration = new CodeMigration(realm, nextPossibleCodeVersion, null); + DataMigration currentDataMigration = new DataMigration(realm, nextPossibleDataVersion, null); SortedSet allCodeMigrations = this.codeMigrations.get(realm); if (allCodeMigrations != null) { diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java index 7df37654f..c14cd7f65 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/MigrationsHandler.java @@ -62,7 +62,7 @@ public class MigrationsHandler extends StrolchComponent { return this.migrations.getMigrationsRan(); } - public Map getCurrentVersions(Certificate cert) { + public Map getCurrentVersions(Certificate cert) { CurrentMigrationVersionQuery query = new CurrentMigrationVersionQuery(getContainer()); query.doQuery(cert); return query.getCurrentVersions(); @@ -75,7 +75,7 @@ public class MigrationsHandler extends StrolchComponent { Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); migrations.parseMigrations(this.migrationsPath); - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); this.migrations = migrations; return this.migrations.getMigrationsToRun(currentVersions); } @@ -87,12 +87,12 @@ public class MigrationsHandler extends StrolchComponent { Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); migrations.parseMigrations(this.migrationsPath); - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); this.migrations.runMigrations(cert, currentVersions); } public void runCodeMigrations(Certificate cert, MapOfLists codeMigrationsByRealm) { - Map currentVersions = getCurrentVersions(cert); + Map currentVersions = getCurrentVersions(cert); Migrations migrations = new Migrations(getContainer(), getContainer().getRealmNames(), this.verbose); this.migrations = migrations; migrations.runCodeMigrations(cert, currentVersions, codeMigrationsByRealm); @@ -138,7 +138,7 @@ public class MigrationsHandler extends StrolchComponent { QueryCurrentVersionsAction queryAction = new QueryCurrentVersionsAction(query); PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction); - Map currentVersions = query.getCurrentVersions(); + Map currentVersions = query.getCurrentVersions(); RunMigrationsAction action = new RunMigrationsAction(this.migrations, currentVersions); @@ -185,7 +185,7 @@ public class MigrationsHandler extends StrolchComponent { QueryCurrentVersionsAction queryAction = new QueryCurrentVersionsAction(query); PrivilegeHandler privilegeHandler = getContainer().getComponent(PrivilegeHandler.class); privilegeHandler.runAsSystem(RealmHandler.SYSTEM_USER_AGENT, queryAction); - Map currentVersions = query.getCurrentVersions(); + Map currentVersions = query.getCurrentVersions(); MigrationsHandler.this.migrations = migrations; if (migrations.getMigrationsToRun(currentVersions).isEmpty()) { diff --git a/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java b/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java index 6f327d329..19e539fcc 100644 --- a/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java +++ b/li.strolch.service/src/main/java/li/strolch/migrations/RunMigrationsAction.java @@ -27,13 +27,13 @@ import ch.eitchnet.utils.Version; public class RunMigrationsAction implements SystemUserAction { private Migrations migrations; - private Map currentVersions; + private Map currentVersions; /** * @param migrations * @param currentVersions */ - public RunMigrationsAction(Migrations migrations, Map currentVersions) { + public RunMigrationsAction(Migrations migrations, Map currentVersions) { this.migrations = migrations; this.currentVersions = currentVersions; } diff --git a/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java index 3cffa4c95..3e4a5b4b3 100644 --- a/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java +++ b/li.strolch.service/src/test/java/li/strolch/migrations/MigrationsTest.java @@ -70,10 +70,10 @@ public class MigrationsTest { public void shouldRunMigrations() { MigrationsHandler migrationsHandler = runtimeMock.getContainer().getComponent(MigrationsHandler.class); - Map currentVersions = migrationsHandler.getCurrentVersions(certificate); + Map currentVersions = migrationsHandler.getCurrentVersions(certificate); String defRealm = StrolchConstants.DEFAULT_REALM; - assertEquals("1.1.1", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists lastMigrations = migrationsHandler.getLastMigrations(); List expectedMigrations = Arrays.asList(Version.valueOf("0.1.0"), Version.valueOf("0.1.1"), @@ -86,8 +86,8 @@ public class MigrationsTest { // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); - assertEquals("1.1.1", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.1.1", currentVersions.get(defRealm).getDataVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getCodeVersion().toString()); MapOfLists codeMigrationsByRealm = new MapOfLists<>(); // add migrations in wrong sequence - should be fixed by migration handler @@ -98,13 +98,13 @@ public class MigrationsTest { lastMigrations = migrationsHandler.getLastMigrations(); assertEquals(1, lastMigrations.keySet().size()); - assertEquals(Arrays.asList(Version.valueOf("1.2.0"), Version.valueOf("1.2.0.a")), + assertEquals(Arrays.asList(Version.valueOf("1.0.0"),Version.valueOf("1.2.0"), Version.valueOf("1.2.0.a")), lastMigrations.getList(defRealm)); // assert new current version currentVersions = migrationsHandler.getCurrentVersions(certificate); - assertEquals("1.2.0.a", currentVersions.get(defRealm).toString()); - assertEquals("0.0.0", currentVersions.get("other").toString()); + assertEquals("1.2.0.a", currentVersions.get(defRealm).getCodeVersion().toString()); + assertEquals("0.0.0", currentVersions.get("other").getDataVersion().toString()); } private static class MyMigration0 extends CodeMigration { @@ -148,7 +148,7 @@ public class MigrationsTest { try (StrolchTransaction tx = openTx(container, cert)) { - Order fooOrder = ModelGenerator.createOrder("foo", "Foo", "Foo"); + Order fooOrder = ModelGenerator.createOrder("foo1", "Foo", "Foo"); AddOrderCommand addOrderCommand = new AddOrderCommand(container, tx); addOrderCommand.setOrder(fooOrder);