From d574b4a059094b26945e9e74ead0f74172d6bc2d Mon Sep 17 00:00:00 2001 From: Colin DAMON Date: Tue, 12 Jul 2022 11:19:16 +0200 Subject: [PATCH] Fix regex replacements --- .../common/domain/ClientsModulesFactory.java | 2 +- .../vue/core/domain/VueModulesFactory.java | 4 +- .../arch/domain/ArchUnitModuleFactory.java | 10 +- .../oauth2/domain/OAuth2ModuleFactory.java | 4 +- .../lite/module/domain/JHipsterModule.java | 40 +++--- .../replacement/ContentReplacement.java | 9 ++ ...ementMatcher.java => ElementReplacer.java} | 2 +- .../domain/replacement/FileReplacer.java | 7 - .../JHipsterModuleMandatoryReplacements.java | 31 ++--- .../JHipsterModuleOptionalReplacements.java | 29 ++-- .../JHipsterModuleReplacements.java | 34 ++--- .../module/domain/replacement/JustAfter.java | 14 -- .../module/domain/replacement/JustBefore.java | 15 --- .../domain/replacement/JustLineAfter.java | 17 --- .../domain/replacement/JustLineBefore.java | 17 --- .../MandatoryReplacementException.java | 10 ++ .../domain/replacement/PositionalMatcher.java | 7 - .../RegexNeedleBeforeReplacer.java | 42 ++++++ .../{RegexMatcher.java => RegexReplacer.java} | 7 +- .../ReplacementErrorException.java | 11 -- .../replacement/TextNeedleBeforeReplacer.java | 83 ++++++++++++ .../{TextMatcher.java => TextReplacer.java} | 5 +- .../UnknownCurrentValueException.java | 5 +- .../FileSystemJHipsterModulesRepository.java | 6 +- .../secondary/FileSystemReplacer.java | 36 +++++ .../module/domain/JHipsterModulesFixture.java | 1 + ...ipsterModuleMandatoryReplacementsTest.java | 84 ++++-------- ...HipsterModuleOptionalReplacementsTest.java | 49 ++++--- .../RegexNeedleBeforeReplacerTest.java | 92 +++++++++++++ ...atcherTest.java => RegexReplacerTest.java} | 13 +- .../TextNeedleBeforeReplacerTest.java | 127 ++++++++++++++++++ ...leSystemJHipsterModulesRepositoryTest.java | 1 + .../secondary/FileSystemReplacerTest.java | 57 ++++++++ 33 files changed, 592 insertions(+), 279 deletions(-) create mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/ContentReplacement.java rename src/main/java/tech/jhipster/lite/module/domain/replacement/{ElementMatcher.java => ElementReplacer.java} (85%) delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/FileReplacer.java delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/JustAfter.java delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/JustBefore.java delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineAfter.java delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineBefore.java create mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/MandatoryReplacementException.java delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/PositionalMatcher.java create mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacer.java rename src/main/java/tech/jhipster/lite/module/domain/replacement/{RegexMatcher.java => RegexReplacer.java} (87%) delete mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/ReplacementErrorException.java create mode 100644 src/main/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacer.java rename src/main/java/tech/jhipster/lite/module/domain/replacement/{TextMatcher.java => TextReplacer.java} (84%) create mode 100644 src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacer.java create mode 100644 src/test/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacerTest.java rename src/test/java/tech/jhipster/lite/module/domain/replacement/{RegexMatcherTest.java => RegexReplacerTest.java} (50%) create mode 100644 src/test/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacerTest.java create mode 100644 src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacerTest.java diff --git a/src/main/java/tech/jhipster/lite/generator/client/common/domain/ClientsModulesFactory.java b/src/main/java/tech/jhipster/lite/generator/client/common/domain/ClientsModulesFactory.java index dc3e08c9a7a..2d5957d64c9 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/common/domain/ClientsModulesFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/client/common/domain/ClientsModulesFactory.java @@ -19,7 +19,7 @@ public static JHipsterModuleBuilder clientModuleBuilder(JHipsterModuleProperties return moduleBuilder(properties) .optionalReplacements() .in("package.json") - .add(justLineBefore(text(CACHE_NEEDLE)), jestSonar(properties.indentation())) + .add(lineBeforeText(CACHE_NEEDLE), jestSonar(properties.indentation())) .and() .and(); } diff --git a/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java b/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java index eef93427eaa..18fc8e529e8 100644 --- a/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/client/vue/core/domain/VueModulesFactory.java @@ -118,8 +118,8 @@ public JHipsterModule buildPiniaModule(JHipsterModuleProperties properties) { .and() .mandatoryReplacements() .in("src/main/webapp/app/main.ts") - .add(justLineBefore(text(IMPORT_NEEDLE)), piniaImports()) - .add(justLineBefore(text(PROVIDER_NEEDLE)), piniaProvider()) + .add(lineBeforeText(IMPORT_NEEDLE), piniaImports()) + .add(lineBeforeText(PROVIDER_NEEDLE), piniaProvider()) .and() .and() .build(); diff --git a/src/main/java/tech/jhipster/lite/generator/server/javatool/arch/domain/ArchUnitModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/javatool/arch/domain/ArchUnitModuleFactory.java index 5380dcbb7f4..8793ba76671 100644 --- a/src/main/java/tech/jhipster/lite/generator/server/javatool/arch/domain/ArchUnitModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/server/javatool/arch/domain/ArchUnitModuleFactory.java @@ -1,12 +1,6 @@ package tech.jhipster.lite.generator.server.javatool.arch.domain; -import static tech.jhipster.lite.module.domain.JHipsterModule.from; -import static tech.jhipster.lite.module.domain.JHipsterModule.javaDependency; -import static tech.jhipster.lite.module.domain.JHipsterModule.justLineBefore; -import static tech.jhipster.lite.module.domain.JHipsterModule.moduleBuilder; -import static tech.jhipster.lite.module.domain.JHipsterModule.text; -import static tech.jhipster.lite.module.domain.JHipsterModule.to; -import static tech.jhipster.lite.module.domain.JHipsterModule.toSrcTestJava; +import static tech.jhipster.lite.module.domain.JHipsterModule.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -43,7 +37,7 @@ public JHipsterModule buildModule(JHipsterModuleProperties properties) { .and() .optionalReplacements() .in("src/test/resources/logback.xml") - .add(justLineBefore(text("")), "") + .add(lineBeforeText(""), "") .and() .and() .build(); diff --git a/src/main/java/tech/jhipster/lite/generator/server/springboot/mvc/security/oauth2/domain/OAuth2ModuleFactory.java b/src/main/java/tech/jhipster/lite/generator/server/springboot/mvc/security/oauth2/domain/OAuth2ModuleFactory.java index 2b25176cef8..15442892a6c 100644 --- a/src/main/java/tech/jhipster/lite/generator/server/springboot/mvc/security/oauth2/domain/OAuth2ModuleFactory.java +++ b/src/main/java/tech/jhipster/lite/generator/server/springboot/mvc/security/oauth2/domain/OAuth2ModuleFactory.java @@ -12,7 +12,7 @@ import tech.jhipster.lite.module.domain.javadependency.JavaDependency; import tech.jhipster.lite.module.domain.javadependency.JavaDependencyScope; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; -import tech.jhipster.lite.module.domain.replacement.TextMatcher; +import tech.jhipster.lite.module.domain.replacement.TextReplacer; public class OAuth2ModuleFactory { @@ -150,7 +150,7 @@ private void appendSpringProperties(JHipsterModuleBuilder builder) { private void appendIntegrationTestAnnotationUpdates(JHipsterModuleBuilder builder, JHipsterModuleProperties properties) { String baseClass = properties.projectBaseName().capitalized() + "App.class"; - TextMatcher importNeedle = text(SPRING_BOOT_IMPORT); + TextReplacer importNeedle = text(SPRING_BOOT_IMPORT); String integrationtTestFile = "src/test/java/" + properties.basePackage().path() + "/IntegrationTest.java"; diff --git a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java index e652a71babc..04bec86c3c0 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java +++ b/src/main/java/tech/jhipster/lite/module/domain/JHipsterModule.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.function.Function; +import java.util.regex.Pattern; import java.util.stream.Stream; import tech.jhipster.lite.error.domain.Assert; import tech.jhipster.lite.module.domain.JHipsterModuleContext.JHipsterModuleContextBuilder; @@ -42,17 +43,14 @@ import tech.jhipster.lite.module.domain.postaction.JHipsterModulePostActions.JHipsterModulePostActionsBuilder; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; -import tech.jhipster.lite.module.domain.replacement.ElementMatcher; import tech.jhipster.lite.module.domain.replacement.JHipsterModuleMandatoryReplacements; import tech.jhipster.lite.module.domain.replacement.JHipsterModuleMandatoryReplacements.JHipsterModuleMandatoryReplacementsBuilder; import tech.jhipster.lite.module.domain.replacement.JHipsterModuleOptionalReplacements; import tech.jhipster.lite.module.domain.replacement.JHipsterModuleOptionalReplacements.JHipsterModuleOptionalReplacementsBuilder; -import tech.jhipster.lite.module.domain.replacement.JustAfter; -import tech.jhipster.lite.module.domain.replacement.JustBefore; -import tech.jhipster.lite.module.domain.replacement.JustLineAfter; -import tech.jhipster.lite.module.domain.replacement.JustLineBefore; -import tech.jhipster.lite.module.domain.replacement.RegexMatcher; -import tech.jhipster.lite.module.domain.replacement.TextMatcher; +import tech.jhipster.lite.module.domain.replacement.RegexNeedleBeforeReplacer; +import tech.jhipster.lite.module.domain.replacement.RegexReplacer; +import tech.jhipster.lite.module.domain.replacement.TextNeedleBeforeReplacer; +import tech.jhipster.lite.module.domain.replacement.TextReplacer; public class JHipsterModule { @@ -161,28 +159,20 @@ public static VersionSlug versionSlug(String versionSlug) { return new VersionSlug(versionSlug); } - public static TextMatcher text(String text) { - return new TextMatcher(text); + public static TextReplacer text(String text) { + return new TextReplacer(text); } - public static RegexMatcher regex(String regex) { - return new RegexMatcher(regex); + public static RegexReplacer regex(String regex) { + return new RegexReplacer(regex); } - public static JustBefore justBefore(ElementMatcher matcher) { - return new JustBefore(matcher); + public static TextNeedleBeforeReplacer lineBeforeText(String needle) { + return new TextNeedleBeforeReplacer(needle); } - public static JustAfter justAfter(ElementMatcher matcher) { - return new JustAfter(matcher); - } - - public static JustLineBefore justLineBefore(ElementMatcher matcher) { - return new JustLineBefore(matcher); - } - - public static JustLineAfter justLineAfter(ElementMatcher matcher) { - return new JustLineAfter(matcher); + public static RegexNeedleBeforeReplacer lineBeforeRegex(String regex) { + return new RegexNeedleBeforeReplacer(Pattern.compile(regex, Pattern.MULTILINE)); } public static PropertyKey propertyKey(String key) { @@ -299,7 +289,7 @@ public JHipsterModuleBuilder documentation(DocumentationTitle title, JHipsterSou files().add(source, to(target)); String markdownLink = "- [" + title.get() + "](" + target + ")"; - optionalReplacements().in(README).add(justLineBefore(text(JHIPSTER_DOCUMENTATION_NEEDLE)), markdownLink); + optionalReplacements().in(README).add(lineBeforeText(JHIPSTER_DOCUMENTATION_NEEDLE), markdownLink); return this; } @@ -307,7 +297,7 @@ public JHipsterModuleBuilder documentation(DocumentationTitle title, JHipsterSou public JHipsterModuleBuilder readmeSection(String section) { Assert.notBlank("section", section); - optionalReplacements().in(README).add(justLineBefore(text(JHIPSTER_README_SECTION_NEEDLE)), section); + optionalReplacements().in(README).add(lineBeforeText(JHIPSTER_README_SECTION_NEEDLE), section); return this; } diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/ContentReplacement.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/ContentReplacement.java new file mode 100644 index 00000000000..c485e7af43c --- /dev/null +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/ContentReplacement.java @@ -0,0 +1,9 @@ +package tech.jhipster.lite.module.domain.replacement; + +public interface ContentReplacement { + String file(); + + String apply(String content); + + void handleError(Throwable e); +} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/ElementMatcher.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/ElementReplacer.java similarity index 85% rename from src/main/java/tech/jhipster/lite/module/domain/replacement/ElementMatcher.java rename to src/main/java/tech/jhipster/lite/module/domain/replacement/ElementReplacer.java index 215184e7b56..bdf0c285b01 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/ElementMatcher.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/ElementReplacer.java @@ -2,7 +2,7 @@ import java.util.function.BiFunction; -public interface ElementMatcher { +public interface ElementReplacer { boolean notMatchIn(String content); BiFunction replacer(); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/FileReplacer.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/FileReplacer.java deleted file mode 100644 index 95575393d22..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/FileReplacer.java +++ /dev/null @@ -1,7 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; - -interface FileReplacer { - void apply(JHipsterProjectFolder folder); -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacements.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacements.java index 3075501ac4b..52170efb72e 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacements.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacements.java @@ -1,12 +1,7 @@ package tech.jhipster.lite.module.domain.replacement; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import tech.jhipster.lite.error.domain.Assert; import tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; -import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; public class JHipsterModuleMandatoryReplacements extends JHipsterModuleReplacements { @@ -44,41 +39,37 @@ private JHipsterModuleFileMandatoryReplacementsBuilder(JHipsterModuleMandatoryRe } @Override - protected FileReplacer buildReplacer(String file, ElementMatcher toReplace, String replacement) { + protected ContentReplacement buildReplacer(String file, ElementReplacer toReplace, String replacement) { return new MandatoryFileReplacer(file, new MandatoryReplacer(toReplace, replacement)); } } - private static record MandatoryFileReplacer(String file, MandatoryReplacer replacement) implements FileReplacer { + private static record MandatoryFileReplacer(String file, MandatoryReplacer replacement) implements ContentReplacement { public MandatoryFileReplacer { Assert.notNull("file", file); Assert.notNull("replacement", replacement); } @Override - public void apply(JHipsterProjectFolder folder) { - Path filePath = folder.filePath(file()); - - try { - String content = Files.readString(filePath); - String updatedContent = replacement().apply(filePath, content); + public String apply(String content) { + return replacement().apply(content); + } - Files.writeString(filePath, updatedContent, StandardOpenOption.TRUNCATE_EXISTING); - } catch (IOException e) { - throw new ReplacementErrorException(filePath, e); - } + @Override + public void handleError(Throwable e) { + throw new MandatoryReplacementException(e); } } - private static record MandatoryReplacer(ElementMatcher currentValue, String updatedValue) { + private static record MandatoryReplacer(ElementReplacer currentValue, String updatedValue) { public MandatoryReplacer { Assert.notNull("currentValue", currentValue); Assert.notNull("updatedValue", updatedValue); } - public String apply(Path file, String content) { + public String apply(String content) { if (currentValue().notMatchIn(content)) { - throw new UnknownCurrentValueException(file, content); + throw new UnknownCurrentValueException(currentValue().searchMatcher(), content); } return currentValue().replacer().apply(content, updatedValue()); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacements.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacements.java index 4a05b963d0f..aec0dc70086 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacements.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacements.java @@ -1,14 +1,9 @@ package tech.jhipster.lite.module.domain.replacement; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tech.jhipster.lite.error.domain.Assert; import tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; -import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; public class JHipsterModuleOptionalReplacements extends JHipsterModuleReplacements { @@ -46,13 +41,13 @@ private JHipsterModuleFileOptionalReplacementsBuilder(JHipsterModuleOptionalRepl } @Override - protected FileReplacer buildReplacer(String file, ElementMatcher toReplace, String replacement) { + protected ContentReplacement buildReplacer(String file, ElementReplacer toReplace, String replacement) { return new OptionalFileReplacer(file, new OptionalReplacer(toReplace, replacement)); } } - private static record OptionalFileReplacer(String file, OptionalReplacer replacement) implements FileReplacer { - private static final Logger log = LoggerFactory.getLogger(FileReplacer.class); + private static record OptionalFileReplacer(String file, OptionalReplacer replacement) implements ContentReplacement { + private static final Logger log = LoggerFactory.getLogger(OptionalFileReplacer.class); public OptionalFileReplacer { Assert.notNull("file", file); @@ -60,21 +55,17 @@ private static record OptionalFileReplacer(String file, OptionalReplacer replace } @Override - public void apply(JHipsterProjectFolder folder) { - Path filePath = folder.filePath(file()); - - try { - String content = Files.readString(filePath); - String updatedContent = replacement().apply(content); + public String apply(String content) { + return replacement().apply(content); + } - Files.writeString(filePath, updatedContent, StandardOpenOption.TRUNCATE_EXISTING); - } catch (IOException e) { - log.debug("Can't replace content, no replacement done {}", e.getMessage(), e); - } + @Override + public void handleError(Throwable e) { + log.debug("Can't apply optional replacement: {}", e.getMessage()); } } - private static record OptionalReplacer(ElementMatcher currentValue, String updatedValue) { + private static record OptionalReplacer(ElementReplacer currentValue, String updatedValue) { public OptionalReplacer { Assert.notNull("currentValue", currentValue); Assert.notNull("updatedValue", updatedValue); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacements.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacements.java index 021a3bb678b..b398de65fc6 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacements.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleReplacements.java @@ -2,25 +2,23 @@ import java.util.ArrayList; import java.util.Collection; +import tech.jhipster.lite.common.domain.JHipsterCollections; import tech.jhipster.lite.error.domain.Assert; import tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; -import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; -abstract class JHipsterModuleReplacements { +public abstract class JHipsterModuleReplacements { - private final Collection replacers; + private final Collection replacements; protected JHipsterModuleReplacements(JHipsterModuleReplacementsBuilder builder) { Assert.notNull("builder", builder); - Assert.notNull("builder", builder.replacers); + Assert.notNull("replacements", builder.replacements); - replacers = builder.replacers; + replacements = JHipsterCollections.immutable(builder.replacements); } - public void apply(JHipsterProjectFolder folder) { - Assert.notNull("folder", folder); - - replacers.forEach(replacement -> replacement.apply(folder)); + public Collection replacements() { + return replacements; } public abstract static class JHipsterModuleReplacementsBuilder< @@ -28,7 +26,7 @@ public abstract static class JHipsterModuleReplacementsBuilder< > { private final JHipsterModuleBuilder module; - private final Collection replacers = new ArrayList<>(); + private final Collection replacements = new ArrayList<>(); protected JHipsterModuleReplacementsBuilder(JHipsterModuleBuilder module) { Assert.notNull("module", module); @@ -40,10 +38,10 @@ public JHipsterModuleBuilder and() { return module; } - void add(FileReplacer fileReplacer) { + void add(ContentReplacement fileReplacer) { Assert.notNull("fileReplacer", fileReplacer); - replacers.add(fileReplacer); + replacements.add(fileReplacer); } public abstract FileReplacementsBuilder in(String file); @@ -67,7 +65,7 @@ protected JHipsterModuleFileReplacementsBuilder(ReplacementsBuilder replacements this.file = file; } - public Builder add(ElementMatcher elementToReplace, String replacement) { + public Builder add(ElementReplacer elementToReplace, String replacement) { Assert.notNull("elementToReplace", elementToReplace); replacements.add(buildReplacer(file, elementToReplace, replacement)); @@ -75,14 +73,6 @@ public Builder add(ElementMatcher elementToReplace, String replacement) { return self(); } - public Builder add(PositionalMatcher positional, String replacement) { - Assert.notNull("PositionalMatcher", positional); - - replacements.add(buildReplacer(file, positional.element(), positional.buildReplacement(replacement))); - - return self(); - } - @SuppressWarnings("unchecked") private Builder self() { return (Builder) this; @@ -92,6 +82,6 @@ public ReplacementsBuilder and() { return replacements; } - protected abstract FileReplacer buildReplacer(String file, ElementMatcher toReplace, String replacement); + protected abstract ContentReplacement buildReplacer(String file, ElementReplacer toReplace, String replacement); } } diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustAfter.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JustAfter.java deleted file mode 100644 index f285a7b7d48..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustAfter.java +++ /dev/null @@ -1,14 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import tech.jhipster.lite.error.domain.Assert; - -public record JustAfter(ElementMatcher element) implements PositionalMatcher { - public JustAfter { - Assert.notNull("element", element); - } - @Override - public String buildReplacement(String value) { - Assert.notBlank("value", value); - return element().searchMatcher().concat(value); - } -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustBefore.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JustBefore.java deleted file mode 100644 index 2c1b18c2272..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustBefore.java +++ /dev/null @@ -1,15 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import tech.jhipster.lite.error.domain.Assert; - -public record JustBefore(ElementMatcher element) implements PositionalMatcher { - public JustBefore { - Assert.notNull("element", element); - } - - @Override - public String buildReplacement(String value) { - Assert.notBlank("value", value); - return value.concat(element().searchMatcher()); - } -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineAfter.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineAfter.java deleted file mode 100644 index b3abfbb9d2e..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineAfter.java +++ /dev/null @@ -1,17 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import tech.jhipster.lite.error.domain.Assert; -import tech.jhipster.lite.module.domain.JHipsterModule; - -public record JustLineAfter(ElementMatcher element) implements PositionalMatcher { - public JustLineAfter { - Assert.notNull("element", element); - } - - @Override - public String buildReplacement(String value) { - Assert.notBlank("value", value); - - return element().searchMatcher().concat(JHipsterModule.LINE_BREAK).concat(value); - } -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineBefore.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineBefore.java deleted file mode 100644 index 67b7da2db10..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/JustLineBefore.java +++ /dev/null @@ -1,17 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import tech.jhipster.lite.error.domain.Assert; -import tech.jhipster.lite.module.domain.JHipsterModule; - -public record JustLineBefore(ElementMatcher element) implements PositionalMatcher { - public JustLineBefore { - Assert.notNull("element", element); - } - - @Override - public String buildReplacement(String value) { - Assert.notBlank("value", value); - - return value.concat(JHipsterModule.LINE_BREAK).concat(element().searchMatcher()); - } -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/MandatoryReplacementException.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/MandatoryReplacementException.java new file mode 100644 index 00000000000..c39559f0b21 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/MandatoryReplacementException.java @@ -0,0 +1,10 @@ +package tech.jhipster.lite.module.domain.replacement; + +import tech.jhipster.lite.error.domain.GeneratorException; + +public class MandatoryReplacementException extends GeneratorException { + + public MandatoryReplacementException(Throwable cause) { + super("Error applying mandatory replacement", cause); + } +} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/PositionalMatcher.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/PositionalMatcher.java deleted file mode 100644 index 8d152aa5cb1..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/PositionalMatcher.java +++ /dev/null @@ -1,7 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -interface PositionalMatcher { - ElementMatcher element(); - - String buildReplacement(String value); -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacer.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacer.java new file mode 100644 index 00000000000..603075828f6 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacer.java @@ -0,0 +1,42 @@ +package tech.jhipster.lite.module.domain.replacement; + +import java.util.function.BiFunction; +import java.util.regex.Pattern; +import tech.jhipster.lite.error.domain.Assert; +import tech.jhipster.lite.module.domain.JHipsterModule; + +public record RegexNeedleBeforeReplacer(Pattern pattern) implements ElementReplacer { + public RegexNeedleBeforeReplacer { + Assert.notNull("pattern", pattern); + } + + @Override + public boolean notMatchIn(String content) { + return !pattern().matcher(content).find(); + } + + @Override + public BiFunction replacer() { + return (content, replacement) -> + linePattern().matcher(content).replaceAll(result -> replacement + JHipsterModule.LINE_BREAK + result.group()); + } + + private Pattern linePattern() { + String stringPattern = searchMatcher(); + + if (isLinePattern(stringPattern)) { + return pattern(); + } + + return Pattern.compile("^.*" + stringPattern, Pattern.MULTILINE); + } + + private boolean isLinePattern(String stringPattern) { + return stringPattern.startsWith("^"); + } + + @Override + public String searchMatcher() { + return pattern().pattern(); + } +} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexMatcher.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexReplacer.java similarity index 87% rename from src/main/java/tech/jhipster/lite/module/domain/replacement/RegexMatcher.java rename to src/main/java/tech/jhipster/lite/module/domain/replacement/RegexReplacer.java index 78cb501cb16..b0b2869ff52 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexMatcher.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/RegexReplacer.java @@ -6,8 +6,8 @@ import tech.jhipster.lite.error.domain.Assert; import tech.jhipster.lite.error.domain.GeneratorException; -public record RegexMatcher(Pattern pattern) implements ElementMatcher { - public RegexMatcher(String regex) { +public record RegexReplacer(Pattern pattern) implements ElementReplacer { + public RegexReplacer(String regex) { this(buildPattern(regex)); } @@ -21,7 +21,7 @@ private static Pattern buildPattern(String regex) { } } - public RegexMatcher { + public RegexReplacer { Assert.notNull("pattern", pattern); } @@ -34,6 +34,7 @@ public boolean notMatchIn(String content) { public BiFunction replacer() { return (content, replacement) -> pattern().matcher(content).replaceAll(replacement); } + @Override public String searchMatcher() { return pattern().pattern(); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/ReplacementErrorException.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/ReplacementErrorException.java deleted file mode 100644 index bd8ed68a30a..00000000000 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/ReplacementErrorException.java +++ /dev/null @@ -1,11 +0,0 @@ -package tech.jhipster.lite.module.domain.replacement; - -import java.nio.file.Path; -import tech.jhipster.lite.error.domain.GeneratorException; - -class ReplacementErrorException extends GeneratorException { - - public ReplacementErrorException(Path file, Throwable e) { - super("Can't apply replacement in " + file.toString() + " (can't update file)", e); - } -} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacer.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacer.java new file mode 100644 index 00000000000..36ff9fb8712 --- /dev/null +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacer.java @@ -0,0 +1,83 @@ +package tech.jhipster.lite.module.domain.replacement; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import tech.jhipster.lite.error.domain.Assert; +import tech.jhipster.lite.module.domain.JHipsterModule; + +public record TextNeedleBeforeReplacer(String text) implements ElementReplacer { + public TextNeedleBeforeReplacer { + Assert.notBlank("text", text); + } + + @Override + public boolean notMatchIn(String content) { + Assert.notNull("content", content); + + return !content.contains(text()); + } + + @Override + public BiFunction replacer() { + return (content, replacement) -> { + List needlesLinesIndexes = needlesLinesIndexes(content); + + if (needlesLinesIndexes.isEmpty()) { + return content; + } + + String replacementBlock = replacement + JHipsterModule.LINE_BREAK; + return buildBlocks(content, needlesLinesIndexes).stream().collect(Collectors.joining(replacementBlock)); + }; + } + + private List needlesLinesIndexes(String content) { + List indexes = new ArrayList<>(); + + int textIndex = content.indexOf(text()); + while (textIndex != -1) { + indexes.add(lineIndex(content, textIndex)); + + textIndex = content.indexOf(text(), textIndex + text().length()); + } + + return indexes; + } + + private int lineIndex(String content, int textIndex) { + int index = content.substring(0, textIndex).lastIndexOf(JHipsterModule.LINE_BREAK); + + if (index == -1) { + return 0; + } + + return index + 1; + } + + private List buildBlocks(String content, List needlesLinesIndexes) { + List blocks = new ArrayList<>(); + + for (int index = 0; index < needlesLinesIndexes.size(); index++) { + blocks.add(content.substring(blockStart(needlesLinesIndexes, index), needlesLinesIndexes.get(index))); + } + + blocks.add(content.substring(needlesLinesIndexes.get(needlesLinesIndexes.size() - 1), content.length())); + + return blocks; + } + + private int blockStart(List needlesLinesIndexes, int index) { + if (index == 0) { + return 0; + } + + return needlesLinesIndexes.get(index - 1); + } + + @Override + public String searchMatcher() { + return text(); + } +} diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/TextMatcher.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/TextReplacer.java similarity index 84% rename from src/main/java/tech/jhipster/lite/module/domain/replacement/TextMatcher.java rename to src/main/java/tech/jhipster/lite/module/domain/replacement/TextReplacer.java index 868471a0409..cca647fd74a 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/TextMatcher.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/TextReplacer.java @@ -3,8 +3,8 @@ import java.util.function.BiFunction; import tech.jhipster.lite.error.domain.Assert; -public record TextMatcher(String text) implements ElementMatcher { - public TextMatcher { +public record TextReplacer(String text) implements ElementReplacer { + public TextReplacer { Assert.notBlank("text", text); } @@ -17,6 +17,7 @@ public boolean notMatchIn(String content) { public BiFunction replacer() { return (content, replacement) -> content.replace(text(), replacement); } + @Override public String searchMatcher() { return text(); diff --git a/src/main/java/tech/jhipster/lite/module/domain/replacement/UnknownCurrentValueException.java b/src/main/java/tech/jhipster/lite/module/domain/replacement/UnknownCurrentValueException.java index f09545b56a6..b4b6c4d4911 100644 --- a/src/main/java/tech/jhipster/lite/module/domain/replacement/UnknownCurrentValueException.java +++ b/src/main/java/tech/jhipster/lite/module/domain/replacement/UnknownCurrentValueException.java @@ -1,11 +1,10 @@ package tech.jhipster.lite.module.domain.replacement; -import java.nio.file.Path; import tech.jhipster.lite.error.domain.GeneratorException; class UnknownCurrentValueException extends GeneratorException { - public UnknownCurrentValueException(Path file, String currentValue) { - super("Can't find \"" + currentValue + "\" in " + file.toString()); + public UnknownCurrentValueException(String currentValue, String content) { + super("Can't find \"" + currentValue + "\" in " + content); } } diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepository.java b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepository.java index a2217cd3ceb..9cf596e6caf 100644 --- a/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepository.java +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepository.java @@ -15,12 +15,14 @@ class FileSystemJHipsterModulesRepository implements JHipsterModulesRepository { private final FileSystemJavaBuildCommandsHandler javaBuild; private final FileSystemSpringPropertiesCommandsHandler springProperties; private final FileSystemPackageJsonHandler packageJson; + private final FileSystemReplacer replacer; public FileSystemJHipsterModulesRepository(ProjectFilesReader filesReader, NpmVersions npmVersions) { files = new FileSystemJHipsterModuleFiles(filesReader); javaBuild = new FileSystemJavaBuildCommandsHandler(); springProperties = new FileSystemSpringPropertiesCommandsHandler(); packageJson = new FileSystemPackageJsonHandler(npmVersions); + replacer = new FileSystemReplacer(); } @Override @@ -33,9 +35,9 @@ public void apply(JHipsterModuleChanges changes) { javaBuild.handle(changes.indentation(), changes.projectFolder(), changes.javaBuildCommands()); springProperties.handle(changes.projectFolder(), changes.springProperties()); packageJson.handle(changes.indentation(), changes.projectFolder(), changes.packageJson()); + replacer.handle(changes.projectFolder(), changes.mandatoryReplacements()); + replacer.handle(changes.projectFolder(), changes.optionalReplacements()); - changes.mandatoryReplacements().apply(changes.projectFolder()); - changes.optionalReplacements().apply(changes.projectFolder()); changes.postActions().run(new JHipsterModuleExecutionContext(changes.projectFolder())); } } diff --git a/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacer.java b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacer.java new file mode 100644 index 00000000000..95b05420daa --- /dev/null +++ b/src/main/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacer.java @@ -0,0 +1,36 @@ +package tech.jhipster.lite.module.infrastructure.secondary; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.function.Consumer; +import tech.jhipster.lite.error.domain.Assert; +import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; +import tech.jhipster.lite.module.domain.replacement.ContentReplacement; +import tech.jhipster.lite.module.domain.replacement.JHipsterModuleReplacements; + +class FileSystemReplacer { + + public void handle(JHipsterProjectFolder projectFolder, JHipsterModuleReplacements replacements) { + Assert.notNull("projectFolder", projectFolder); + Assert.notNull("replacements", replacements); + + replacements.replacements().forEach(applyReplacement(projectFolder)); + } + + private Consumer applyReplacement(JHipsterProjectFolder projectFolder) { + return replacement -> { + Path filePath = projectFolder.filePath(replacement.file()); + + try { + String content = Files.readString(filePath); + String updatedContent = replacement.apply(content); + + Files.writeString(filePath, updatedContent, StandardOpenOption.TRUNCATE_EXISTING); + } catch (IOException e) { + replacement.handleError(e); + } + }; + } +} diff --git a/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java b/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java index 1239e546764..d1e3dadc2d2 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java +++ b/src/test/java/tech/jhipster/lite/module/domain/JHipsterModulesFixture.java @@ -59,6 +59,7 @@ public static JHipsterModule module() { .in("src/main/java/com/company/myapp/errors/Assert.java") .add(text("Ensure that the given collection is not empty"), "Dummy collection replacement") .add(regex("if the collection is [^ ]+ or empty"), "Another dummy collection replacement") + .add(lineBeforeRegex("public static class IntegerAsserter\\s*\\{"), " // Dummy comment") .and() .in("dummy") .add(text("Ensure that the input is not null"), "Dummy replacement") diff --git a/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsTest.java b/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsTest.java index 1e48c4f86bc..b5283d1a9fa 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsTest.java +++ b/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleMandatoryReplacementsTest.java @@ -1,82 +1,52 @@ package tech.jhipster.lite.module.domain.replacement; import static org.assertj.core.api.Assertions.*; -import static tech.jhipster.lite.TestUtils.*; import static tech.jhipster.lite.module.domain.JHipsterModule.*; -import static tech.jhipster.lite.module.infrastructure.secondary.JHipsterModulesAssertions.*; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collection; import org.junit.jupiter.api.Test; -import tech.jhipster.lite.TestUtils; import tech.jhipster.lite.UnitTest; -import tech.jhipster.lite.generator.project.domain.Project; +import tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; @UnitTest class JHipsterModuleMandatoryReplacementsTest { - @Test - void shouldNotApplyReplacementOnUnknownFile() { - assertThatThrownBy(() -> replaceIn("unknown")).isExactlyInstanceOf(ReplacementErrorException.class); - } - @Test void shouldNotApplyReplacementOnUnknownCurrentValue() { - assertThatThrownBy(() -> replaceIn("maven/pom.xml")).isExactlyInstanceOf(UnknownCurrentValueException.class); + assertThatThrownBy(() -> replaceIn("src/test/resources/projects/maven/pom.xml")) + .isExactlyInstanceOf(UnknownCurrentValueException.class); } - @Test - void shouldApplyCorrectTextMatcherPlacement() { - Project project = tmpProjectWithPackageJsonComplete(); - TestUtils.copyPomXml(project); + private static String replaceIn(String file) { + JHipsterProjectFolder folder = new JHipsterProjectFolder("src/test/resources/projects"); + JHipsterModuleBuilder module = moduleBuilder(JHipsterModuleProperties.defaultProperties(folder)); - JHipsterProjectFolder folder = new JHipsterProjectFolder(project.getFolder()); - JHipsterModuleBuilder module = moduleBuilder(JHipsterModuleProperties.defaultProperties(folder)) - .mandatoryReplacements() - .in("pom.xml") - .add(justBefore(new TextMatcher("")), "Before") - .add(justAfter(new TextMatcher("")), "aFter") - .add(justLineBefore(new TextMatcher("4.0.0")), "BeforeLine") - .add(justLineAfter(new TextMatcher("4.0.0")), "AfterLine") + Collection replacements = JHipsterModuleMandatoryReplacements + .builder(module) + .in(file) + .add(new TextReplacer("old"), "new") .and() - .and(); - - assertThatModule(module.build()) - .createFile("pom.xml") - .containing("Before") - .containing("aFter") - .containing("BeforeLine\n4.0.0") - .containing("4.0.0\nAfterLine"); - } - - @Test - void shouldApplyCorrectRegexMatcherPlacement() { - Project project = tmpProjectWithPackageJsonComplete(); - TestUtils.copyPomXml(project); + .build() + .replacements(); - JHipsterProjectFolder folder = new JHipsterProjectFolder(project.getFolder()); - JHipsterModuleBuilder module = moduleBuilder(JHipsterModuleProperties.defaultProperties(folder)) - .mandatoryReplacements() - .in("pom.xml") - .add(justBefore(new RegexMatcher("")), "Before") - .add(justAfter(new RegexMatcher("")), "aFter") - .add(justLineBefore(new RegexMatcher("4.0.0")), "BeforeLine") - .add(justLineAfter(new RegexMatcher("4.0.0")), "AfterLine") - .and() - .and(); + String result = readContent(file); + for (ContentReplacement replacement : replacements) { + result = replacement.apply(result); + } - assertThatModule(module.build()) - .createFile("pom.xml") - .containing("Before") - .containing("aFter") - .containing("BeforeLine\n4.0.0") - .containing("4.0.0\nAfterLine"); + return result; } - private static void replaceIn(String file) { - JHipsterProjectFolder folder = new JHipsterProjectFolder("src/test/resources/projects"); - JHipsterModuleBuilder module = moduleBuilder(JHipsterModuleProperties.defaultProperties(folder)); - - JHipsterModuleMandatoryReplacements.builder(module).in(file).add(new TextMatcher("old"), "new").and().build().apply(folder); + private static String readContent(String file) { + try { + return Files.readString(Paths.get(file)); + } catch (IOException e) { + throw new AssertionError(); + } } } diff --git a/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsTest.java b/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsTest.java index 260957150dd..5c964044ded 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsTest.java +++ b/src/test/java/tech/jhipster/lite/module/domain/replacement/JHipsterModuleOptionalReplacementsTest.java @@ -3,40 +3,49 @@ import static org.assertj.core.api.Assertions.*; import static tech.jhipster.lite.module.domain.JHipsterModule.*; -import ch.qos.logback.classic.Level; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collection; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import tech.jhipster.lite.LogsSpy; import tech.jhipster.lite.UnitTest; +import tech.jhipster.lite.module.domain.JHipsterModule.JHipsterModuleBuilder; import tech.jhipster.lite.module.domain.properties.JHipsterModuleProperties; import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; @UnitTest -@ExtendWith(LogsSpy.class) class JHipsterModuleOptionalReplacementsTest { - private final LogsSpy logs; - - public JHipsterModuleOptionalReplacementsTest(LogsSpy logs) { - this.logs = logs; - } - - @Test - void shouldSilentlyNotApplyReplacementOnUnknownFile() { - assertThatCode(() -> replaceIn("unknown")).doesNotThrowAnyException(); - - logs.shouldHave(Level.DEBUG, "no replacement done"); - } - @Test void shouldSilentlyNotApplyReplacementOnUnknownCurrentValue() { - assertThatCode(() -> replaceIn("maven/pom.xml")).doesNotThrowAnyException(); + assertThatCode(() -> replaceIn("src/test/resources/projects/maven/pom.xml")).doesNotThrowAnyException(); } - private static void replaceIn(String file) { + private static String replaceIn(String file) { JHipsterProjectFolder folder = new JHipsterProjectFolder("src/test/resources/projects"); JHipsterModuleBuilder module = moduleBuilder(JHipsterModuleProperties.defaultProperties(folder)); - JHipsterModuleOptionalReplacements.builder(module).in(file).add(new TextMatcher("old"), "new").and().build().apply(folder); + Collection replacements = JHipsterModuleOptionalReplacements + .builder(module) + .in(file) + .add(new TextReplacer("old"), "new") + .and() + .build() + .replacements(); + + String result = readContent(file); + for (ContentReplacement replacement : replacements) { + result = replacement.apply(result); + } + + return result; + } + + private static String readContent(String file) { + try { + return Files.readString(Paths.get(file)); + } catch (IOException e) { + throw new AssertionError(); + } } } diff --git a/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacerTest.java b/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacerTest.java new file mode 100644 index 00000000000..a358f39e5ae --- /dev/null +++ b/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexNeedleBeforeReplacerTest.java @@ -0,0 +1,92 @@ +package tech.jhipster.lite.module.domain.replacement; + +import static org.assertj.core.api.Assertions.*; + +import java.util.regex.Pattern; +import org.junit.jupiter.api.Test; +import tech.jhipster.lite.UnitTest; + +@UnitTest +class RegexNeedleBeforeReplacerTest { + + @Test + void shouldNotMatchNotMatchingRegex() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile("pattern")); + + assertThat(replacer.notMatchIn("content")).isTrue(); + } + + @Test + void shouldMatchMatchingRegex() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile("cont[en]{2}t")); + + assertThat(replacer.notMatchIn("content")).isFalse(); + } + + @Test + void shouldNotReplaceNotMatchingNeedle() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile("ne{1,2}dle")); + + String updatedContent = replacer.replacer().apply("content", "replacement"); + + assertThat(updatedContent).isEqualTo("content"); + } + + @Test + void shouldReplaceLineStartNeedle() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile("^ + + """, ""); + + assertThat(updatedContent).isEqualTo(""" + + + + + """); + } + + @Test + void shouldReplaceLinePartNeedle() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile(" + + + + """, + "" + ); + + assertThat(updatedContent) + .isEqualTo( + """ + + + + + + + + """ + ); + } + + @Test + void shouldGetPatternAsSearchMatcher() { + RegexNeedleBeforeReplacer replacer = new RegexNeedleBeforeReplacer(Pattern.compile("cont[en]{2}t")); + + assertThat(replacer.searchMatcher()).isEqualTo("cont[en]{2}t"); + } +} diff --git a/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexMatcherTest.java b/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexReplacerTest.java similarity index 50% rename from src/test/java/tech/jhipster/lite/module/domain/replacement/RegexMatcherTest.java rename to src/test/java/tech/jhipster/lite/module/domain/replacement/RegexReplacerTest.java index b8a0ccc37ab..c182b4a7a6e 100644 --- a/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexMatcherTest.java +++ b/src/test/java/tech/jhipster/lite/module/domain/replacement/RegexReplacerTest.java @@ -7,20 +7,25 @@ import tech.jhipster.lite.error.domain.GeneratorException; @UnitTest -class RegexMatcherTest { +class RegexReplacerTest { @Test void shouldNotBuildWithInvalidPattern() { - assertThatThrownBy(() -> new RegexMatcher("{")).isExactlyInstanceOf(GeneratorException.class); + assertThatThrownBy(() -> new RegexReplacer("{")).isExactlyInstanceOf(GeneratorException.class); } @Test void shouldNotMatchNotMatchingPattern() { - assertThat(new RegexMatcher("pouet").notMatchIn("toto")).isTrue(); + assertThat(new RegexReplacer("pouet").notMatchIn("toto")).isTrue(); } @Test void shouldMatchMatchingPattern() { - assertThat(new RegexMatcher("pouet").notMatchIn("pouet")).isFalse(); + assertThat(new RegexReplacer("pouet").notMatchIn("pouet")).isFalse(); + } + + @Test + void shouldGetPatternAsSearchMatcher() { + assertThat(new RegexReplacer("pouet").searchMatcher()).isEqualTo("pouet"); } } diff --git a/src/test/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacerTest.java b/src/test/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacerTest.java new file mode 100644 index 00000000000..30c13a5895c --- /dev/null +++ b/src/test/java/tech/jhipster/lite/module/domain/replacement/TextNeedleBeforeReplacerTest.java @@ -0,0 +1,127 @@ +package tech.jhipster.lite.module.domain.replacement; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import tech.jhipster.lite.UnitTest; + +@UnitTest +class TextNeedleBeforeReplacerTest { + + @Test + void shouldNotMatchUnknownText() { + assertThat(new TextNeedleBeforeReplacer("unknown").notMatchIn("content")).isTrue(); + } + + @Test + void shouldMatchKnownText() { + assertThat(new TextNeedleBeforeReplacer("known").notMatchIn("unknown")).isFalse(); + } + + @Test + void shouldNotReplaceUnknownNeedle() { + TextNeedleBeforeReplacer replacer = new TextNeedleBeforeReplacer(""); + + String updatedContent = replacer.replacer().apply("", ""); + + assertThat(updatedContent).isEqualTo(""); + } + + @Test + void shouldInsertTextLineBeforeFirstLineNeedle() { + TextNeedleBeforeReplacer replacer = new TextNeedleBeforeReplacer(""); + + String updatedContent = replacer.replacer().apply(""" + + """, ""); + + assertThat(updatedContent).isEqualTo(""" + + + """); + } + + @Test + void shouldInsertTextLineBeforeNeedleLine() { + TextNeedleBeforeReplacer replacer = new TextNeedleBeforeReplacer(""); + + String updatedContent = replacer + .replacer() + .apply(""" + + + + """, ""); + + assertThat(updatedContent).isEqualTo(""" + + + + + """); + } + + @Test + void shouldInsertTextLineBeforeNeedleLinePart() { + TextNeedleBeforeReplacer replacer = new TextNeedleBeforeReplacer(""); + + String updatedContent = replacer + .replacer() + .apply(""" + + + + + """, ""); + + assertThat(updatedContent) + .isEqualTo(""" + + + + + + """); + } + + @Test + void shouldReplaceMultipleNeedles() { + TextNeedleBeforeReplacer replacer = new TextNeedleBeforeReplacer(""); + + String updatedContent = replacer + .replacer() + .apply( + """ + + + + + + with trailling text + + """, + "" + ); + + assertThat(updatedContent) + .isEqualTo( + """ + + + + + + + + + with trailling text + + """ + ); + } + + @Test + void shouldGetTextAsMatcher() { + assertThat(new TextNeedleBeforeReplacer("known").searchMatcher()).isEqualTo("known"); + } +} diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepositoryTest.java b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepositoryTest.java index deea0585478..34dd9f337d7 100644 --- a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepositoryTest.java +++ b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemJHipsterModulesRepositoryTest.java @@ -189,6 +189,7 @@ void shouldApplyModule() { .containing("Another dummy replacement") .containing("Dummy collection replacement") .containing("Another dummy collection replacement") + .containing("// Dummy comment\n public static class IntegerAsserter {") .and() .createFile("src/main/resources/config/application.properties") .containing("springdoc.swagger-ui.operationsSorter=alpha") diff --git a/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacerTest.java b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacerTest.java new file mode 100644 index 00000000000..1f1f7ab1b2d --- /dev/null +++ b/src/test/java/tech/jhipster/lite/module/infrastructure/secondary/FileSystemReplacerTest.java @@ -0,0 +1,57 @@ +package tech.jhipster.lite.module.infrastructure.secondary; + +import static org.assertj.core.api.Assertions.*; +import static tech.jhipster.lite.module.domain.JHipsterModulesFixture.*; + +import ch.qos.logback.classic.Level; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import tech.jhipster.lite.LogsSpy; +import tech.jhipster.lite.TestFileUtils; +import tech.jhipster.lite.UnitTest; +import tech.jhipster.lite.module.domain.properties.JHipsterProjectFolder; +import tech.jhipster.lite.module.domain.replacement.JHipsterModuleMandatoryReplacements; +import tech.jhipster.lite.module.domain.replacement.JHipsterModuleOptionalReplacements; +import tech.jhipster.lite.module.domain.replacement.MandatoryReplacementException; +import tech.jhipster.lite.module.domain.replacement.TextReplacer; + +@UnitTest +@ExtendWith(LogsSpy.class) +class FileSystemReplacerTest { + + private static final FileSystemReplacer replacer = new FileSystemReplacer(); + + private final LogsSpy logs; + + public FileSystemReplacerTest(LogsSpy logs) { + this.logs = logs; + } + + @Test + void shouldHandleMandatoryReplacementError() { + String path = TestFileUtils.tmpDirForTest(); + + assertThatThrownBy(() -> + replacer.handle( + new JHipsterProjectFolder(path), + JHipsterModuleMandatoryReplacements.builder(emptyModuleBuilder()).in("unknown").add(new TextReplacer("old"), "new").and().build() + ) + ) + .isExactlyInstanceOf(MandatoryReplacementException.class); + } + + @Test + void shouldHandleOptionalReplacementError() { + String path = TestFileUtils.tmpDirForTest(); + + assertThatCode(() -> + replacer.handle( + new JHipsterProjectFolder(path), + JHipsterModuleOptionalReplacements.builder(emptyModuleBuilder()).in("unknown").add(new TextReplacer("old"), "new").and().build() + ) + ) + .doesNotThrowAnyException(); + + logs.shouldHave(Level.DEBUG, "Can't apply optional replacement"); + } +}