diff --git a/Readme.md b/Readme.md index cd48339..845af9a 100644 --- a/Readme.md +++ b/Readme.md @@ -22,7 +22,7 @@ Module Updates funktionieren hierbei genauso wie SimpleUpdates. Es gibt 3 versch * Yaml Bootstrap Files * Tasks die nachdem Bootstrap ausgeführt werden sollen -Jedes Module muss eine Version gesetzt haben und muss mit einem Timestamp (ddMMyyyyHHmm) starten. +Jedes ModuleUpdate File muss der folgenden NamingConvention entsprechen `V_.java`. ## Allgemeine Funktionsweise diff --git a/pom.xml b/pom.xml index f503288..83ed607 100644 --- a/pom.xml +++ b/pom.xml @@ -6,10 +6,11 @@ 21 6.2.46 1.18.34 + 5.13.0 at.ucs.magnolia ucs-intranet-magnolia-updates - 1.0.0 + 1.0.1 ucs-intranet-magnolia-updates http://maven.apache.org jar @@ -42,7 +43,12 @@ junit junit - 3.8.1 + test + + + org.mockito + mockito-core + ${version.mockito} test diff --git a/src/main/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandler.java b/src/main/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandler.java index ffdf9ee..b40d406 100644 --- a/src/main/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandler.java +++ b/src/main/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandler.java @@ -2,6 +2,7 @@ package at.ucs.magnolia.updates; import at.ucs.magnolia.updates.util.TaskWrapper; import at.ucs.magnolia.updates.util.VersionComparator; +import at.ucs.magnolia.updates.util.VersionNumberUtil; import at.ucs.magnolia.updates.util.VersionUtil; import info.magnolia.module.DefaultModuleVersionHandler; import info.magnolia.module.InstallContext; @@ -9,6 +10,7 @@ import info.magnolia.module.delta.Delta; import info.magnolia.module.delta.DeltaBuilder; import info.magnolia.module.delta.Task; import info.magnolia.module.model.Version; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; @@ -20,10 +22,17 @@ import java.util.*; import java.util.function.Predicate; import java.util.stream.IntStream; +@Getter @Slf4j -public abstract class IntranetUpdateModuleVersionHandler extends DefaultModuleVersionHandler { +public class IntranetUpdateModuleVersionHandler extends DefaultModuleVersionHandler { + + protected IntranetUpdateModuleConfig moduleConfig; + + public IntranetUpdateModuleVersionHandler(IntranetUpdateModuleConfig moduleConfig){ + super(); + this.moduleConfig = moduleConfig; + } - protected abstract IntranetUpdateModuleConfig getModuleConfig(); @Override protected List getExtraInstallTasks(InstallContext installContext) { @@ -62,9 +71,7 @@ public abstract class IntranetUpdateModuleVersionHandler extends DefaultModuleVe private ModuleUpdate initiateModuleUpdate(Class moduleUpdateClass) { try { - ModuleUpdate moduleUpdate = moduleUpdateClass.getConstructor().newInstance(); - moduleUpdate.setYamlPath(getModuleConfig().getYamlUpdateDir()); - return moduleUpdate; + return moduleUpdateClass.getConstructor().newInstance(); } catch (RuntimeException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { @@ -84,11 +91,13 @@ public abstract class IntranetUpdateModuleVersionHandler extends DefaultModuleVe } private Delta buildDelta(InstallContext installContext, ModuleUpdate moduleUpdate) { - final String version = moduleUpdate.getVersion(); - List wrappedTasks = IntStream.range(0, moduleUpdate.getAllTasks().size()) + + final String version = VersionNumberUtil.getVersion(moduleUpdate); + List moduleUpdateTasks = moduleUpdate.getAllTasks(moduleConfig,version); + List wrappedTasks = IntStream.range(0,moduleUpdateTasks .size()) .mapToObj(i -> { final String wrappedVersion = MessageFormat.format("{0}_{1}", version, i); - final Task task = moduleUpdate.getAllTasks().get(i); + final Task task = moduleUpdateTasks.get(i); return new TaskWrapper(task, wrappedVersion); }) .filter(installNecessary(installContext)) diff --git a/src/main/java/at/ucs/magnolia/updates/ModuleUpdate.java b/src/main/java/at/ucs/magnolia/updates/ModuleUpdate.java index 291f4b3..ab61994 100644 --- a/src/main/java/at/ucs/magnolia/updates/ModuleUpdate.java +++ b/src/main/java/at/ucs/magnolia/updates/ModuleUpdate.java @@ -3,22 +3,16 @@ package at.ucs.magnolia.updates; import at.ucs.magnolia.updates.util.BootstrapUpdateYamlsWithProperties; import at.ucs.magnolia.updates.util.LoggingTask; import info.magnolia.module.delta.Task; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; -@Getter -@Setter @RequiredArgsConstructor public abstract class ModuleUpdate { - private final String version; - private String yamlPath; public List getUpdateTasks() { return Collections.emptyList(); @@ -28,14 +22,14 @@ public abstract class ModuleUpdate { return Collections.emptyList(); } - public List getAllTasks() { + public List getAllTasks(IntranetUpdateModuleConfig config, String version) { List tasks = new ArrayList<>(); tasks.add(new LoggingTask("updating to version: " + version, "")); tasks.addAll(getUpdateTasks()); tasks.add(new LoggingTask("Importing bootsrap Yamls for: " + version, "")); tasks.add(new BootstrapUpdateYamlsWithProperties( "Import bootstrap YAML folder", - MessageFormat.format("Imports bootstrap YAML files from {0}{1}", yamlPath, version), version, yamlPath)); + MessageFormat.format("Imports bootstrap YAML files from {0}{1}", config.getYamlUpdateDir(), version), version, config.getYamlUpdateDir())); tasks.addAll(getUpdateTasksAfterBootstrap()); return tasks; } diff --git a/src/main/java/at/ucs/magnolia/updates/util/TaskWrapper.java b/src/main/java/at/ucs/magnolia/updates/util/TaskWrapper.java index 88dd59e..7dfeca2 100644 --- a/src/main/java/at/ucs/magnolia/updates/util/TaskWrapper.java +++ b/src/main/java/at/ucs/magnolia/updates/util/TaskWrapper.java @@ -8,14 +8,13 @@ import info.magnolia.module.delta.TaskExecutionException; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import javax.jcr.Node; import javax.jcr.RepositoryException; +@Getter @Slf4j public class TaskWrapper extends AbstractTask { private final Task task; - @Getter private final String version; public TaskWrapper(Task task, String version) { diff --git a/src/main/java/at/ucs/magnolia/updates/util/VersionComparator.java b/src/main/java/at/ucs/magnolia/updates/util/VersionComparator.java index 5c4288f..4dd4a2b 100644 --- a/src/main/java/at/ucs/magnolia/updates/util/VersionComparator.java +++ b/src/main/java/at/ucs/magnolia/updates/util/VersionComparator.java @@ -9,14 +9,15 @@ import java.util.Comparator; @Slf4j public class VersionComparator implements Comparator { + public static final String VERSION_DATE_FORMAT = "yyyyMMddHHmmss"; @Override public int compare(ModuleUpdate o1, ModuleUpdate o2) { - var o1Version = o1.getVersion(); - var o2Version = o2.getVersion(); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("ddMMyyyyHHmm"); - LocalDateTime first = LocalDateTime.from(dateTimeFormatter.parse(o1Version.substring(0, 12))); - LocalDateTime second = LocalDateTime.from(dateTimeFormatter.parse(o2Version.substring(0, 12))); + var o1Version = VersionNumberUtil.getVersion(o1); + var o2Version = VersionNumberUtil.getVersion(o2); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(VERSION_DATE_FORMAT); + LocalDateTime first = LocalDateTime.from(dateTimeFormatter.parse(o1Version)); + LocalDateTime second = LocalDateTime.from(dateTimeFormatter.parse(o2Version)); return first.compareTo(second); } diff --git a/src/main/java/at/ucs/magnolia/updates/util/VersionNumberUtil.java b/src/main/java/at/ucs/magnolia/updates/util/VersionNumberUtil.java new file mode 100644 index 0000000..5a420d7 --- /dev/null +++ b/src/main/java/at/ucs/magnolia/updates/util/VersionNumberUtil.java @@ -0,0 +1,15 @@ +package at.ucs.magnolia.updates.util; + +import at.ucs.magnolia.updates.ModuleUpdate; +import org.apache.commons.lang3.StringUtils; + +public class VersionNumberUtil { + + public static String getVersion(ModuleUpdate update) { + if (update == null) { + return null; + } + return StringUtils.substring(update.getClass().getSimpleName(), 1, VersionComparator.VERSION_DATE_FORMAT.length()+1); + } + +} diff --git a/src/main/java/at/ucs/magnolia/updates/util/VersionUtil.java b/src/main/java/at/ucs/magnolia/updates/util/VersionUtil.java index 05a40fa..d32476b 100644 --- a/src/main/java/at/ucs/magnolia/updates/util/VersionUtil.java +++ b/src/main/java/at/ucs/magnolia/updates/util/VersionUtil.java @@ -38,4 +38,5 @@ public class VersionUtil { } } + } diff --git a/src/test/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandlerTest.java b/src/test/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandlerTest.java new file mode 100644 index 0000000..6111a2a --- /dev/null +++ b/src/test/java/at/ucs/magnolia/updates/IntranetUpdateModuleVersionHandlerTest.java @@ -0,0 +1,159 @@ +package at.ucs.magnolia.updates; + + +import at.ucs.magnolia.updates.util.TaskWrapper; +import at.ucs.magnolia.updates.util.VersionUtil; +import info.magnolia.module.InstallContext; +import info.magnolia.module.delta.Delta; +import info.magnolia.module.delta.Task; +import info.magnolia.module.model.ModuleDefinition; +import info.magnolia.module.model.Version; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import javax.jcr.RepositoryException; +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +public class IntranetUpdateModuleVersionHandlerTest { + + private static final List appliedUpdates = new ArrayList<>(); + + @Test + public void testGetDeltas_mustReturnSimpleTask() throws RepositoryException { + try (MockedStatic utilities = Mockito.mockStatic(VersionUtil.class)) { + mockVersionUtil(utilities); + InstallContext installContext = Mockito.mock(InstallContext.class); + ModuleDefinition moduleDefinition = Mockito.mock(ModuleDefinition.class); + Mockito.when(installContext.getCurrentModuleDefinition()).thenReturn(moduleDefinition); + Mockito.when(moduleDefinition.getVersion()).thenReturn(Version.parseVersion("9.9.9")); + IntranetUpdateModuleConfig config = new IntranetUpdateModuleConfig() { + @Override + public List getInitialUpdateTasks() { + return List.of(); + } + + @Override + public String getYamlUpdateDir() { + return ""; + } + + @Override + public String getUpdateTaskPackage() { + return "at.ucs.magnolia.updates.test.updates1"; + } + }; + List deltas = new IntranetUpdateModuleVersionHandler(config).getDeltas(installContext, installContext.getCurrentModuleDefinition().getVersion()); + assertThat(deltas.size(), equalTo(1)); + // the TestTask contained by the class V20241125113012_TestUpdate1 should be returned + List matching = deltas.stream().flatMap(delta -> delta.getTasks().stream()).filter( task -> (task instanceof TaskWrapper && ((TaskWrapper)task).getTask() instanceof TestTask) || (task instanceof TestTask)).toList(); + assertThat("count of testtask must be 1", matching.size(), equalTo(1)); + + } + } + + + @Test + public void testGetDeltas_mustReturnAlsoInstallTasks() throws RepositoryException { + try (MockedStatic utilities = Mockito.mockStatic(VersionUtil.class)) { + mockVersionUtil(utilities); + InstallContext installContext = Mockito.mock(InstallContext.class); + ModuleDefinition moduleDefinition = Mockito.mock(ModuleDefinition.class); + Mockito.when(installContext.getCurrentModuleDefinition()).thenReturn(moduleDefinition); + Mockito.when(moduleDefinition.getVersion()).thenReturn(null); + IntranetUpdateModuleConfig config = new IntranetUpdateModuleConfig() { + @Override + public List getInitialUpdateTasks() { + return List.of(new TestTask("install1","install1desc")); + } + @Override + public String getYamlUpdateDir() { + return ""; + } + + @Override + public String getUpdateTaskPackage() { + return "at.ucs.magnolia.updates.test.updates1"; + } + }; + List deltas = new IntranetUpdateModuleVersionHandler(config).getDeltas(installContext, installContext.getCurrentModuleDefinition().getVersion()); + assertThat(deltas.size(), equalTo(2)); + // the TestTask contained by the class V20241125113012_TestUpdate1 must be returned + // The TestTask returned by the IntranetUpdateModuleConfig#getInitialUpdateTasks must be contained + List matching = deltas.stream().flatMap(delta -> delta.getTasks().stream()).filter( task -> (task instanceof TaskWrapper && ((TaskWrapper)task).getTask() instanceof TestTask) || (task instanceof TestTask)).toList(); + assertThat("count of testtask must be 2", matching.size(), equalTo(2)); + + } + } + + @Test + public void testGetDeltas_mustNotReturnInstallTasks() throws RepositoryException { + try (MockedStatic utilities = Mockito.mockStatic(VersionUtil.class)) { + mockVersionUtil(utilities); + InstallContext installContext = Mockito.mock(InstallContext.class); + ModuleDefinition moduleDefinition = Mockito.mock(ModuleDefinition.class); + Mockito.when(installContext.getCurrentModuleDefinition()).thenReturn(moduleDefinition); + Mockito.when(moduleDefinition.getVersion()).thenReturn(Version.parseVersion("9.9.9")); + IntranetUpdateModuleConfig config = new IntranetUpdateModuleConfig() { + @Override + public List getInitialUpdateTasks() { + return List.of(new TestTask("install1","install1desc")); + } + @Override + public String getYamlUpdateDir() { + return ""; + } + @Override + public String getUpdateTaskPackage() { + return "at.ucs.magnolia.updates.test.updates1"; + } + }; + List deltas = new IntranetUpdateModuleVersionHandler(config).getDeltas(installContext, installContext.getCurrentModuleDefinition().getVersion()); + assertThat(deltas.size(), equalTo(1)); + // the TestTask contained by the class V20241125113012_TestUpdate1 should be returned + // The TestTask returned by the IntranetUpdateModuleConfig#getInitialUpdateTasks must not be contained + + List matching = deltas.stream().flatMap(delta -> delta.getTasks().stream()).filter( task -> (task instanceof TaskWrapper && ((TaskWrapper)task).getTask() instanceof TestTask) || (task instanceof TestTask)).toList(); + assertThat("count of testtask must be 1", matching.size(), equalTo(1)); + + + } + } + + private void mockVersionUtil(MockedStatic utilities) throws RepositoryException { + utilities.when(() -> VersionUtil.containsVersion(Mockito.any(), Mockito.any())) + .thenAnswer( + invocation -> { + String version = invocation.getArgument(1, String.class); + return appliedUpdates.contains(version); + } + ); + + utilities.when(() -> VersionUtil.addVersion(Mockito.any(), Mockito.any(), Mockito.any())) + .thenAnswer( + invocation -> { + String version = invocation.getArgument(1, String.class); + return appliedUpdates.add(version); + } + ); + + utilities.when(() -> VersionUtil.addVersion(Mockito.any(), Mockito.any(), Mockito.any())) + .thenAnswer( + invocation -> { + String version = invocation.getArgument(1, String.class); + return appliedUpdates.add(version); + } + ); + String testVersion = "123456"; + assertThat(VersionUtil.containsVersion(null, testVersion), equalTo(false)); + VersionUtil.addVersion(null, testVersion, null); + assertThat(VersionUtil.containsVersion(null, testVersion), equalTo(true)); + // cleanup versions + appliedUpdates.clear(); + } + +} \ No newline at end of file diff --git a/src/test/java/at/ucs/magnolia/updates/TestTask.java b/src/test/java/at/ucs/magnolia/updates/TestTask.java new file mode 100644 index 0000000..8927de5 --- /dev/null +++ b/src/test/java/at/ucs/magnolia/updates/TestTask.java @@ -0,0 +1,10 @@ +package at.ucs.magnolia.updates; + +import at.ucs.magnolia.updates.util.LoggingTask; + +public class TestTask extends LoggingTask { + + public TestTask(String taskName, String taskDescription) { + super(taskName, taskDescription); + } +} \ No newline at end of file diff --git a/src/test/java/at/ucs/magnolia/updates/test/updates1/V20241125113012_TestUpdate1.java b/src/test/java/at/ucs/magnolia/updates/test/updates1/V20241125113012_TestUpdate1.java new file mode 100644 index 0000000..dbae341 --- /dev/null +++ b/src/test/java/at/ucs/magnolia/updates/test/updates1/V20241125113012_TestUpdate1.java @@ -0,0 +1,15 @@ +package at.ucs.magnolia.updates.test.updates1; + +import at.ucs.magnolia.updates.ModuleUpdate; +import at.ucs.magnolia.updates.TestTask; +import info.magnolia.module.delta.Task; + +import java.util.List; + +public class V20241125113012_TestUpdate1 extends ModuleUpdate { + + @Override + public List getUpdateTasks() { + return List.of(new TestTask("test1","V20241125113012_TestUpdate1")); + } +} diff --git a/src/test/java/at/ucs/magnolia/updates/util/VersionNumberUtilTest.java b/src/test/java/at/ucs/magnolia/updates/util/VersionNumberUtilTest.java new file mode 100644 index 0000000..e7f8eac --- /dev/null +++ b/src/test/java/at/ucs/magnolia/updates/util/VersionNumberUtilTest.java @@ -0,0 +1,17 @@ +package at.ucs.magnolia.updates.util; + + +import at.ucs.magnolia.updates.test.updates1.V20241125113012_TestUpdate1; +import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class VersionNumberUtilTest { + + @Test + public void testGetVersion() { + + String version = VersionNumberUtil.getVersion(new V20241125113012_TestUpdate1()); + assertThat("version must match",version,equalTo("20241125113012")); + } +}