diff --git a/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParam.java b/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParam.java new file mode 100644 index 0000000..0b4d470 --- /dev/null +++ b/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParam.java @@ -0,0 +1,116 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * 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 + *

+ * https://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 org.openrewrite.openapi.swagger; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Preconditions; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.AnnotationMatcher; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.search.UsesMethod; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; + +import java.util.ArrayList; +import java.util.List; + +public class MigrateApiImplicitParam extends Recipe { + private static final String FQN_SCHEMA = "io.swagger.v3.oas.annotations.media.Schema"; + + @Override + public String getDisplayName() { + return "Migrate `@ApiImplicitParam` to `@Parameter)`"; + } + + @Override + public String getDescription() { + return "Migrate `@ApiImplicitParam` to `@Parameter`."; + } + + @Override + public TreeVisitor getVisitor() { + // This recipe is after ChangeType recipe + return Preconditions.check( + Preconditions.or( + new UsesMethod<>("io.swagger.annotations.ApiImplicitParam dataTypeClass()", false), + new UsesMethod<>("io.swagger.annotations.ApiImplicitParam defaultValue()", false) + ), + new JavaIsoVisitor() { + @Override + public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) { + J.Annotation anno = super.visitAnnotation(annotation, ctx); + + if (!new AnnotationMatcher("io.swagger.v3.oas.annotations.Parameter").matches(anno)) { + return anno; + } + + StringBuilder tpl = new StringBuilder(); + StringBuilder schemaTpl = new StringBuilder(); + List args = new ArrayList<>(); + for (Expression exp : anno.getArguments()) { + if (isDataTypeClass(exp)) { + Expression expression = ((J.Assignment) exp).getAssignment(); + addSchema(schemaTpl, "implementation"); + args.add(expression); + } else if (isDefaultValue(exp)) { + Expression expression = ((J.Assignment) exp).getAssignment(); + addSchema(schemaTpl, "defaultValue"); + args.add(expression); + } else { + tpl.append("#{any()}, "); + args.add(exp); + } + } + if (tpl.toString().endsWith(", ")) { + tpl.delete(tpl.length() - 2, tpl.length()); + } + if (schemaTpl.length() > 0) { + if (schemaTpl.toString().endsWith(", ")) { + schemaTpl.delete(schemaTpl.length() - 2, schemaTpl.length()); + } + schemaTpl.append(")"); + tpl.append(", ").append(schemaTpl); + } + anno = JavaTemplate.builder(tpl.toString()) + .imports(FQN_SCHEMA) + .javaParser(JavaParser.fromJavaVersion().classpath("swagger-annotations")) + .build() + .apply(updateCursor(anno), annotation.getCoordinates().replaceArguments(), args.toArray()); + maybeAddImport(FQN_SCHEMA, false); + return maybeAutoFormat(annotation, anno, ctx, getCursor().getParentTreeCursor()); + } + + private void addSchema(StringBuilder tpl, String key) { + if (tpl.length() == 0) { + tpl.append("schema = @Schema("); + } + tpl.append(key).append(" = #{any()}, "); + } + + private boolean isDataTypeClass(Expression exp) { + return exp instanceof J.Assignment && ((J.Identifier) ((J.Assignment) exp).getVariable()).getSimpleName().equals("dataTypeClass"); + } + + private boolean isDefaultValue(Expression exp) { + return exp instanceof J.Assignment && ((J.Identifier) ((J.Assignment) exp).getVariable()).getSimpleName().equals("defaultValue"); + } + } + ); + } +} diff --git a/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParamDataTypeClass.java b/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParamDataTypeClass.java deleted file mode 100644 index a7ef2f1..0000000 --- a/src/main/java/org/openrewrite/openapi/swagger/MigrateApiImplicitParamDataTypeClass.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2024 the original author or authors. - *

- * 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 - *

- * https://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 org.openrewrite.openapi.swagger; - -import org.openrewrite.ExecutionContext; -import org.openrewrite.Preconditions; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; -import org.openrewrite.java.AnnotationMatcher; -import org.openrewrite.java.JavaIsoVisitor; -import org.openrewrite.java.JavaParser; -import org.openrewrite.java.JavaTemplate; -import org.openrewrite.java.search.UsesMethod; -import org.openrewrite.java.tree.Expression; -import org.openrewrite.java.tree.J; - -import java.util.ArrayList; -import java.util.List; - -public class MigrateApiImplicitParamDataTypeClass extends Recipe { - private static final String FQN_SCHEMA = "io.swagger.v3.oas.annotations.media.Schema"; - - @Override - public String getDisplayName() { - return "Migrate `@ApiImplicitParam(dataTypeClass=Foo.class)` to `@Parameter(schema=@Schema(implementation=Foo.class))`"; - } - - @Override - public String getDescription() { - return "Migrate `@ApiImplicitParam(dataTypeClass=Foo.class)` to `@Parameter(schema=@Schema(implementation=Foo.class))`."; - } - - @Override - public TreeVisitor getVisitor() { - // This recipe is after ChangeType recipe - return Preconditions.check( - new UsesMethod<>("io.swagger.annotations.ApiImplicitParam dataTypeClass()", false), - new JavaIsoVisitor() { - @Override - public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ctx) { - J.Annotation anno = super.visitAnnotation(annotation, ctx); - - if (!new AnnotationMatcher("io.swagger.v3.oas.annotations.Parameter").matches(anno)) { - return anno; - } - - StringBuilder tpl = new StringBuilder(); - List args = new ArrayList<>(); - for (Expression exp : anno.getArguments()) { - if (!args.isEmpty()) { - tpl.append(", "); - } - if (isDataTypeClass(exp)) { - J.FieldAccess fieldAccess = (J.FieldAccess) ((J.Assignment) exp).getAssignment(); - tpl.append("schema = @Schema(implementation = #{any()})"); - args.add(fieldAccess); - } else { - tpl.append("#{any()}"); - args.add(exp); - } - } - anno = JavaTemplate.builder(tpl.toString()) - .imports(FQN_SCHEMA) - .javaParser(JavaParser.fromJavaVersion().classpath("swagger-annotations")) - .build() - .apply(updateCursor(anno), annotation.getCoordinates().replaceArguments(), args.toArray()); - maybeAddImport(FQN_SCHEMA, false); - return maybeAutoFormat(annotation, anno, ctx, getCursor().getParentTreeCursor()); - } - - private boolean isDataTypeClass(Expression exp) { - return exp instanceof J.Assignment && ((J.Identifier) ((J.Assignment) exp).getVariable()).getSimpleName().equals("dataTypeClass"); - } - } - ); - } -} diff --git a/src/main/resources/META-INF/rewrite/swagger-2.yml b/src/main/resources/META-INF/rewrite/swagger-2.yml index 0865a56..adef3f3 100644 --- a/src/main/resources/META-INF/rewrite/swagger-2.yml +++ b/src/main/resources/META-INF/rewrite/swagger-2.yml @@ -197,7 +197,7 @@ recipeList: - org.openrewrite.java.RemoveAnnotationAttribute: annotationType: io.swagger.v3.oas.annotations.Parameter attributeName: allowMultiple - - org.openrewrite.openapi.swagger.MigrateApiImplicitParamDataTypeClass + - org.openrewrite.openapi.swagger.MigrateApiImplicitParam --- type: specs.openrewrite.org/v1beta/recipe diff --git a/src/test/java/org/openrewrite/openapi/swagger/SwaggerToOpenAPITest.java b/src/test/java/org/openrewrite/openapi/swagger/SwaggerToOpenAPITest.java index a0f8ea4..9c0015b 100644 --- a/src/test/java/org/openrewrite/openapi/swagger/SwaggerToOpenAPITest.java +++ b/src/test/java/org/openrewrite/openapi/swagger/SwaggerToOpenAPITest.java @@ -128,7 +128,7 @@ class Example { } @Test - void migrateApiImplicitParamDataTypeClass() { + void migrateApiImplicitParam() { rewriteRun( //language=java java( @@ -136,7 +136,7 @@ void migrateApiImplicitParamDataTypeClass() { import io.swagger.annotations.ApiImplicitParam; class Example { - @ApiImplicitParam(name = "foo", value = "Foo object", required = true, dataTypeClass = Example.class) + @ApiImplicitParam(name = "foo", value = "Foo object", required = true, dataTypeClass = Example.class, defaultValue = "example") public void create(Example foo) { } } @@ -146,7 +146,7 @@ public void create(Example foo) { import io.swagger.v3.oas.annotations.media.Schema; class Example { - @Parameter(name = "foo", description = "Foo object", required = true, schema = @Schema(implementation = Example.class)) + @Parameter(name = "foo", description = "Foo object", required = true, schema = @Schema(implementation = Example.class, defaultValue = "example")) public void create(Example foo) { } }