diff --git a/spring-data-eclipse-store-migration/pom.xml b/spring-data-eclipse-store-migration/pom.xml index 97eb63b..4f1b5c3 100644 --- a/spring-data-eclipse-store-migration/pom.xml +++ b/spring-data-eclipse-store-migration/pom.xml @@ -50,7 +50,7 @@ 2.6.3 3.2.2 - 1.0.0 + 1.0.1 1.18.30 @@ -115,7 +115,7 @@ org.openrewrite - rewrite-maven + rewrite-properties org.projectlombok @@ -136,7 +136,6 @@ ${software.xdev.spring.data.eclipse.store.version} runtime - org.openrewrite rewrite-java-17 @@ -152,7 +151,6 @@ slf4j-simple test - diff --git a/spring-data-eclipse-store-migration/src/main/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExists.java b/spring-data-eclipse-store-migration/src/main/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExists.java new file mode 100644 index 0000000..895344f --- /dev/null +++ b/spring-data-eclipse-store-migration/src/main/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExists.java @@ -0,0 +1,108 @@ +/* + * Copyright © 2023 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.xdev.spring.data.eclipse.store; + +import org.jetbrains.annotations.NotNull; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.properties.AddProperty; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class AddPropertyIfClassExists extends Recipe +{ + @Option(displayName = "Class that must exist in the classpath to add the property", + description = "Name of the class that must exist in the classpath to execute the recipe to add a property in the properties file.", + example = "software.xdev") + private String className; + + @Option( + displayName = "Property key", + description = "The property key to add.", + example = "management.metrics.enable.process.files" + ) + private String property; + @Option( + displayName = "Property value", + description = "The value of the new property key." + ) + private String value; + @Option( + displayName = "Optional comment to be prepended to the property", + description = "A comment that will be added to the new property.", + required = false, + example = "This is a comment" + ) + private @Nullable String comment; + @Option( + displayName = "Optional delimiter", + description = "Property entries support different delimiters (`=`, `:`, or whitespace). The default value is " + + "`=` unless provided the delimiter of the new property entry.", + required = false, + example = ":" + ) + private @Nullable String delimiter; + + @Override + public @NotNull String getDisplayName() + { + return "AddValueToAnnotationIfDependencyExists"; + } + + @Override + public @NotNull String getDescription() + { + return "::::TODO:::Add the a new annotation to an existing annotation."; + } + + @Override + public @NotNull TreeVisitor getVisitor() + { + if(!this.doesClasspathContainClass(this.className)) + { + return TreeVisitor.noop(); + } + return new AddProperty( + this.property, this.value, this.comment, this.delimiter + ).getVisitor(); + } + + private boolean doesClasspathContainClass(final String classToCheck) + { + try + { + Class.forName(classToCheck, false, this.getClass().getClassLoader()); + return true; + } + catch(final ClassNotFoundException e) + { + return false; + } + } +} diff --git a/spring-data-eclipse-store-migration/src/main/resources/META-INF/rewrite/rewrite.yml b/spring-data-eclipse-store-migration/src/main/resources/META-INF/rewrite/rewrite.yml index 611e5a0..6608973 100644 --- a/spring-data-eclipse-store-migration/src/main/resources/META-INF/rewrite/rewrite.yml +++ b/spring-data-eclipse-store-migration/src/main/resources/META-INF/rewrite/rewrite.yml @@ -16,10 +16,17 @@ recipeList: classPath: 'spring-data-eclipse-store' annotationTypeToAddSimpleName: 'EnableEclipseStoreRepositories' + - software.xdev.spring.data.eclipse.store.AddPropertyIfClassExists: + className: 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration' + property: 'spring.autoconfigure.exclude' + value: 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration' + comment: 'This suppresses the use of JPA in the project. It is needed to let EclipseStore coexist with JPA.' + delimiter: = + - org.openrewrite.maven.AddDependency: groupId: software.xdev artifactId: spring-data-eclipse-store - version: 1.0.1 + version: 1.0.2 acceptTransitive: true - org.openrewrite.maven.AddPlugin: @@ -36,3 +43,34 @@ recipeList: - org.openrewrite.java.RemoveAnnotation: # https://docs.openrewrite.org/reference/method-patterns annotationPattern: '@org.springframework.data.jpa.repository.Query *(..)' + + - org.openrewrite.java.RemoveAnnotation: + annotationPattern: '@org.springframework.data.jpa.repository.config.EnableJpaRepositories *(..)' + + # Change all the spring framework repositories to specifically use EclipseStore repositories. + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.repository.Repository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreCustomRepository + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.repository.CrudRepository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreCrudRepository + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.repository.ListCrudRepository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreListCrudRepository + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.repository.PagingAndSortingRepositoryRepository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStorePagingAndSortingRepositoryRepository + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.repository.ListPagingAndSortingRepositoryRepository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreListPagingAndSortingRepositoryRepository + + # Change all the JPA repositories to specifically use EclipseStore repositories. + + - org.openrewrite.java.ChangeType: + oldFullyQualifiedTypeName: org.springframework.data.jpa.repository.JpaRepository + newFullyQualifiedTypeName: software.xdev.spring.data.eclipse.store.repository.interfaces.EclipseStoreRepository diff --git a/spring-data-eclipse-store-migration/src/test/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExistsTest.java b/spring-data-eclipse-store-migration/src/test/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExistsTest.java new file mode 100644 index 0000000..5d5babd --- /dev/null +++ b/spring-data-eclipse-store-migration/src/test/java/software/xdev/spring/data/eclipse/store/AddPropertyIfClassExistsTest.java @@ -0,0 +1,119 @@ +/* + * Copyright © 2023 XDEV Software (https://xdev.software) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.xdev.spring.data.eclipse.store; + +import static org.openrewrite.properties.Assertions.properties; + +import org.junit.jupiter.api.Test; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; + + +class AddPropertyIfClassExistsTest implements RewriteTest +{ + + @Override + public void defaults(final RecipeSpec recipeSpec) + { + recipeSpec + .recipe(new AddPropertyIfClassExists( + HibernateJpaAutoConfiguration.class.getName(), + "spring.autoconfigure.exclude", + DataSourceAutoConfiguration.class.getName() + + "," + + DataSourceTransactionManagerAutoConfiguration.class.getName() + + "," + + HibernateJpaAutoConfiguration.class.getName(), + "", + "=")); + } + + @Test + void testSimple() + { + this.rewriteRun + ( + properties( + "", + """ + spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + """ + ) + ); + } + + /** + * It's not clear if this is a desired behavior, but since the Open Rewrite Recipe + * {@link org.openrewrite.properties.AddProperty} is doing this, and we are only using this recipe, this is how it + * works now. + *

+ * Might change in the future. + *

+ */ + @Test + void testMultipleProperties() + { + this.rewriteRun + ( + properties( + "", + """ + spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + """ + ), + properties( + "", + """ + spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + """ + ) + ); + } + + @Test + void testExisting() + { + this.rewriteRun + ( + properties( + """ + spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + """ + ) + ); + } + + @Test + void testClassNotExisting() + { + this.rewriteRun + ( + recipeSpec -> + recipeSpec.recipe(new AddPropertyIfClassExists( + "not.existing.Class", + "spring.autoconfigure.exclude", + "DummyValue", + "", + "=")), + properties( + "" + ) + ); + } +}