diff --git a/eng/versioning/external_dependencies.txt b/eng/versioning/external_dependencies.txt
index a8fe028ca1af7..398a653808ddc 100644
--- a/eng/versioning/external_dependencies.txt
+++ b/eng/versioning/external_dependencies.txt
@@ -16,6 +16,7 @@ com.fasterxml.jackson.core:jackson-core;2.17.2
com.fasterxml.jackson.core:jackson-databind;2.17.2
com.fasterxml.jackson.dataformat:jackson-dataformat-avro;2.17.2
com.fasterxml.jackson.dataformat:jackson-dataformat-xml;2.17.2
+com.fasterxml.jackson.dataformat:jackson-dataformat-smile;2.17.2
com.fasterxml.jackson.datatype:jackson-datatype-jsr310;2.17.2
com.fasterxml.jackson.module:jackson-module-afterburner;2.17.2
com.fasterxml.jackson.module:jackson-module-blackbird;2.17.2
@@ -98,6 +99,7 @@ io.lettuce:lettuce-core;6.4.0.RELEASE
org.redisson:redisson;3.36.0
testdep_net.bytebuddy:byte-buddy;1.15.5
testdep_net.bytebuddy:byte-buddy-agent;1.15.5
+org.openrewrite.recipe:rewrite-recipe-bom;3.0.2
## Spring boot dependency versions
org.springframework.boot:spring-boot-maven-plugin;2.7.18
diff --git a/eng/versioning/version_client.txt b/eng/versioning/version_client.txt
index c1184dbef8b25..6b4449f29e556 100644
--- a/eng/versioning/version_client.txt
+++ b/eng/versioning/version_client.txt
@@ -170,6 +170,7 @@ com.azure:azure-monitor-ingestion;1.2.7;1.3.0-beta.1
com.azure:azure-monitor-ingestion-perf;1.0.0-beta.1;1.0.0-beta.1
com.azure:azure-monitor-query;1.5.4;1.6.0-beta.1
com.azure:azure-monitor-query-perf;1.0.0-beta.1;1.0.0-beta.1
+com.azure:azure-openrewrite;1.0.0-beta.1;1.0.0-beta.1
com.azure:azure-perf-test-parent;1.0.0-beta.1;1.0.0-beta.1
com.azure:azure-quantum-jobs;1.0.0-beta.1;1.0.0-beta.2
com.azure:azure-search-documents;11.7.4;11.8.0-beta.5
@@ -485,6 +486,7 @@ io.clientcore:http-okhttp3;1.0.0-beta.1;1.0.0-beta.1
io.clientcore:http-stress;1.0.0-beta.1;1.0.0-beta.1
io.clientcore:optional-dependency-tests;1.0.0-beta.1;1.0.0-beta.1
+
# Unreleased dependencies: Copy the entry from above, prepend "unreleased_" and remove the current
# version. Unreleased dependencies are only valid for dependency versions.
# Format;
diff --git a/sdk/tools/azure-openrewrite/CHANGELOG.md b/sdk/tools/azure-openrewrite/CHANGELOG.md
new file mode 100644
index 0000000000000..8b33f0fedccc1
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Release History
+
+## 1.0.0-beta.1 (Unreleased)
+
+### Features Added
+
+### Breaking Changes
+
+### Bugs Fixed
+
+### Other Changes
\ No newline at end of file
diff --git a/sdk/tools/azure-openrewrite/MIGRATION.md b/sdk/tools/azure-openrewrite/MIGRATION.md
new file mode 100644
index 0000000000000..24410baff7dac
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/MIGRATION.md
@@ -0,0 +1,89 @@
+# Azure Code Migration with OpenRewrite
+
+This library contains integrations for OpenRewrite with Maven for code migrating Azure SDK libraries
+such as `azure-core` to `azure-core-v2`.
+
+## Setup
+
+### Prerequisites
+The following tools are required to build and execute this project:
+- Java (version 8 or higher)
+- Maven
+
+### Recipe Configuration
+
+The migration recipe is defined in the `azure-openrewrite` module as detailed below:
+
+```yaml
+### Recipe Configuration for OpenRewrite
+type: specs.openrewrite.org/v1beta/recipe
+name: com.azure.openrewrite.migrateToVNext
+displayName: Migrate from azure-core to azure-core-v2
+description: This recipe migrates the azure sdk libraries from azure-core to azure-core-v2 and clientcore libraries.
+recipeList:
+ ...
+```
+You can find the full recipe configuration in the `rewrite.yml` file [here](https://github.com/Azure/azsdk-java-rewrite-recipes/blob/main/rewrite-java-core/src/main/resources/META-INF/rewrite/rewrite.yml).
+
+
+## Usage
+### Maven Plugin Configuration
+The OpenRewrite Maven plugin is configured in the `rewrite-java-core` module to run the migration recipe on the sample project
+as follows:
+```xml
+
+ org.openrewrite.maven
+ rewrite-maven-plugin
+ 5.7.1
+
+
+ com.azure.openrewrite.migrateToVNext
+
+
+
+
+ com.azure
+ azure-openrewrite
+ 1.0.0
+
+
+
+```
+The plugin configuration is defined in the `pom.xml` file [here](https://github.com/Azure/azsdk-java-rewrite-recipes/blob/main/rewrite-sample/pom.xml).
+
+## Execution
+The `rewrite-sample` module is configured to use the `openrewrite-maven-plugin` to run the OpenRewrite recipe on the sample project.
+The `rewrite-sample` module contains the modules `azure-ai-translation-text-v1` and `azure-ai-translation-text-v2`
+to demonstrate the migration of code from `azure-core` to `azure-core-v2`.
+
+**Note:** To execute the below commands, ensure that you are within the `rewrite-sample` directory.
+
+### Dry Run
+To run the OpenRewrite recipe in dry-run mode, execute the following command:
+```shell
+mvn rewrite:dryRun
+```
+If the above command is not recognised, execute the full version of the command:
+
+```shell
+mvn org.openrewrite.maven:rewrite-maven-plugin:dryRun
+```
+
+This will generate a file `rewrite.patch` in `rewrite-sample/target/rewrite` directory.
+
+### Run (apply changes)
+To actually apply the changes to the sample project, execute the following command:
+```shell
+mvn rewrite:run
+```
+If the above command is not recognised, execute the full version of the command:
+
+```shell
+mvn org.openrewrite.maven:rewrite-maven-plugin:run
+```
+
+## Testing
+To run the unit tests for the OpenRewrite recipe, execute the following command:
+```shell
+mvn:test
+```
diff --git a/sdk/tools/azure-openrewrite/README.MD b/sdk/tools/azure-openrewrite/README.MD
new file mode 100644
index 0000000000000..41f504fb329bc
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/README.MD
@@ -0,0 +1,7 @@
+# Azure OpenRewrite Plugin library for Java
+## Getting started
+## Key concepts
+## Examples
+## Troubleshooting
+## Next steps
+## Contributing
diff --git a/sdk/tools/azure-openrewrite/pom.xml b/sdk/tools/azure-openrewrite/pom.xml
new file mode 100644
index 0000000000000..a773fb3c617c4
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/pom.xml
@@ -0,0 +1,131 @@
+
+
+ 4.0.0
+
+ com.azure
+ azure-openrewrite
+ 1.0.0-beta.1
+
+ Microsoft Azure OpenRewrite Plugin library for Java
+ This module contains OpenRewrite recipe for migrating to next generation Microsoft Azure client libraries.
+
+
+
+
+ org.openrewrite.recipe
+ rewrite-recipe-bom
+ 3.0.2
+ pom
+ import
+
+
+
+
+
+
+
+ org.openrewrite
+ rewrite-java
+ compile
+
+
+
+
+ org.openrewrite
+ rewrite-java-8
+ test
+
+
+
+
+ org.openrewrite
+ rewrite-maven
+ compile
+
+
+ com.azure
+ azure-core
+ 1.54.1
+ test
+
+
+ org.openrewrite
+ rewrite-test
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.11.4
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.11.4
+ test
+
+
+
+ org.assertj
+ assertj-core
+ 3.26.0
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.17.2
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-smile
+ 2.17.2
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.17.2
+
+
+ org.projectlombok
+ lombok
+ 1.18.34
+ provided
+
+
+
+ com.azure
+ azure-ai-translation-text
+ 1.1.0
+ test
+
+
+
+ com.azure
+ azure-storage-blob
+ 12.29.0
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.15.0
+
+
+
+
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/AddTryCatchToMethodCallRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/AddTryCatchToMethodCallRecipe.java
new file mode 100644
index 0000000000000..f0414f56fc994
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/AddTryCatchToMethodCallRecipe.java
@@ -0,0 +1,324 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import org.openrewrite.Cursor;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.NlsRewrite;
+import org.openrewrite.Option;
+import org.openrewrite.Recipe;
+import org.openrewrite.Tree;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.internal.ListUtils;
+import org.openrewrite.internal.lang.NonNull;
+import org.openrewrite.internal.lang.Nullable;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.MethodMatcher;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.openrewrite.java.tree.Expression;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.MethodCall;
+import org.openrewrite.java.tree.Statement;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+
+/**
+ * Add try-catch to method recipe places all calls to methods matching the provided method
+ * pattern in a try-catch block based off the template provided.
+ * Recipe will attempt to use the JavaParser first, but will also run on code that cannot be
+ * parsed by Open Rewrites Java parser.
+ * Recipe does not check if the method throws the supplied exception, only that the method is
+ * in a suitable try-catch block.
+ * If the template is not syntactically correct, the recipe will not make any changes.
+ */
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class AddTryCatchToMethodCallRecipe extends Recipe {
+
+ @Option(displayName = "Method pattern",
+ description = "A method pattern used to find matching method declaration.",
+ example = "*..* hello(..)")
+ @NonNull
+ String methodPattern;
+
+ @Option(displayName = "Catch template",
+ description = "The code snippet to be executed in the catch block",
+ example = "catch (IOException e) { e.printStackTrace(); }")
+ @NonNull
+ String catchTemplateString;
+
+ @Option(displayName = "Exclude owner of method",
+ description = "When enabled, the owner (class) from which the method originates from will not be matched during search.",
+ required = false)
+ @NonNull
+ boolean excludeOwner;
+
+ @Option(displayName = "Fully qualified exception name",
+ description = "The fully qualified type name for the caught exception",
+ example = "java.io.IOException")
+ @NonNull
+ String fullyQualifiedExceptionName;
+
+ /**
+ * All recipes must be serializable. This is verified by RewriteTest.rewriteRun() in your tests.
+ * Json creator allows your recipes to be used from a yaml file.
+ */
+ @JsonCreator
+ public AddTryCatchToMethodCallRecipe(@NonNull @JsonProperty("methodPattern") String methodPattern,
+ @NonNull @JsonProperty("catchTemplateString") String catchTemplateString,
+ @NonNull @JsonProperty("fullyQualifiedExceptionName") String fullyQualifiedExceptionName,
+ @Nullable @JsonProperty("excludeOwner") boolean excludeOwner) {
+ this.methodPattern = methodPattern;
+ this.excludeOwner = excludeOwner;
+ this.catchTemplateString = catchTemplateString;
+ this.fullyQualifiedExceptionName = fullyQualifiedExceptionName;
+ }
+
+
+ @Override
+ public @NlsRewrite.DisplayName String getDisplayName() {
+ return "Add try-catch to method";
+ }
+
+ @Override
+ public @NlsRewrite.Description String getDescription() {
+ return "Surrounds calls to the target method in a custom try-catch block.";
+ }
+
+ /**
+ * Method to return the visitor that performs the checks and changes
+ *
+ * @return Returns the visitor that performs the checks and changes
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new AddTryCatchVisitor();
+ }
+
+ /**
+ * Visitor that performs the checks and changes
+ */
+ private class AddTryCatchVisitor extends JavaIsoVisitor {
+
+ private final MethodMatcher methodMatcher = new MethodMatcher(methodPattern, true);
+
+ /**
+ * Overridden visitBlock method performs the changes to methods filtered by visitMethodCall.
+ */
+ @Override
+ public J.Block visitBlock(J.Block block, ExecutionContext context) {
+ J.Block body = super.visitBlock(block, context);
+
+ // Get the method that needs to be changed
+ MethodCall method = getCursor().pollMessage("METHOD");
+ if (method == null) {
+ return body;
+ }
+
+ //Get the parents of the method
+ Tree parent = getCursor().pollMessage("PARENT");
+ // Get the first statement parent of method
+ Statement parentStatement = getCursor().pollMessage("STATEMENT");
+
+ JavaTemplate tryCatchTemplate = JavaTemplate.builder("try { int a = null; a = 3; } " + catchTemplateString)
+ .imports(fullyQualifiedExceptionName)
+ .build();
+
+ // Create an empty block to apply the try-catch template based off the cursor values from the main body
+ // This should create the correct formatting.
+ J.Block b = J.Block.createEmptyBlock();
+ b = tryCatchTemplate.apply(new Cursor(getCursor(),b), b.getCoordinates().firstStatement());
+ int parentIndex;
+
+ // Extract the try-catch block and dummy elements
+ J.Try _try = (J.Try) b.getStatements().get(0);
+ J.VariableDeclarations dummyVarDec = (J.VariableDeclarations) _try.getBody().getStatements().get(0);
+ J.Assignment dummyAssignment = (J.Assignment) _try.getBody().getStatements().get(1);
+
+ if (_try.getCatches().isEmpty()) {
+ return body;
+ }
+ // The original list of statements to alter
+ List bodyStatements = body.getStatements();
+
+ // Method is the first element on its line.
+ if (parent == null) {
+ // Cast method as a statement and update the indentation (prefix)
+
+ Statement methodStatement = method.withPrefix(dummyVarDec.getPrefix());
+ parentIndex = body.getStatements().indexOf(methodStatement);
+ // Make it the only statement in the try block
+ _try = _try.withBody(_try.getBody().withStatements(ListUtils.insert(
+ new ArrayList<>(), methodStatement, 0 )));
+
+ // Update the statements
+ bodyStatements.set(parentIndex, _try);
+ }
+ else if (parent instanceof J.Assignment) {
+ parentIndex = body.getStatements().indexOf(parent);
+ J.Assignment new_assignment = ((J.Assignment) parent).withPrefix(dummyAssignment.getPrefix());
+
+ _try = _try.withBody(_try.getBody().withStatements(ListUtils.insert(
+ new ArrayList<>(), new_assignment, 0 )));
+
+ bodyStatements.set(parentIndex, _try);
+ }
+ else if (parentStatement instanceof J.VariableDeclarations) {
+
+ J.VariableDeclarations parentVd = (J.VariableDeclarations) parentStatement;
+ parentIndex = body.getStatements().indexOf(parentVd);
+
+ if (parentVd.getVariables().size() != 1) {
+ // Recipe can only handle a variable declaration with a single named variable at this time
+ // Could be changed.
+ return body;
+ }
+
+ J.VariableDeclarations.NamedVariable namedVariable = parentVd.getVariables().get(0);
+ Expression expression = namedVariable.getInitializer();
+
+ assert expression != null;
+ // Repurpose the dummyAssignment variable
+ dummyAssignment = dummyAssignment.withVariable(namedVariable.getName().unwrap());
+ dummyAssignment = dummyAssignment.withAssignment(expression);
+
+ _try = _try.withBody(_try.getBody().withStatements(ListUtils.insert(
+ new ArrayList<>(), dummyAssignment, 0 )));
+
+ // Make the original declaration initialise with '= null'
+ namedVariable = namedVariable.withInitializer(dummyVarDec.getVariables().get(0).getInitializer());
+
+ parentVd = parentVd.withVariables(ListUtils.insert(
+ new ArrayList<>(), namedVariable, 0 ));
+
+ // Replace the old VariableDeclarations
+ bodyStatements.set(parentIndex, parentVd);
+ // Add the try below it
+ bodyStatements.add(parentIndex +1, _try);
+
+ }
+ else { // Wrap method call in try catch for all other cases
+ int i = 0;
+ int index = -1;
+ for (Statement statement : body.getStatements()) {
+ if (statement.print().contains(method.print())) {
+ index = i;
+ }
+ i ++;
+ }
+ String tryCatchBlock = String.format(
+ "try { %s; } %s", body.getStatements().get(index), catchTemplateString
+ );
+ JavaTemplate tryCatchNewTemplate = JavaTemplate.builder(tryCatchBlock)
+ .imports(fullyQualifiedExceptionName)
+ .build();
+
+ // Create an empty block to apply the try-catch template based off the cursor values from the main body
+ // This should create the correct formatting.
+ J.Block newBlock = J.Block.createEmptyBlock();
+ newBlock = tryCatchNewTemplate.apply(new Cursor(getCursor(),newBlock), newBlock.getCoordinates().firstStatement());
+
+ bodyStatements.remove(index);
+ for (Statement statement : newBlock.getStatements()) {
+ bodyStatements.add(index, statement);
+ }
+ }
+
+ // Update the body block with the new set of statements and return.
+ body = body.withStatements(bodyStatements);
+ // Add the import if needed
+ maybeAddImport(fullyQualifiedExceptionName,false);
+ return body;
+ }
+ public boolean containsSubstringWithParenthesis(String input, String substring) {
+ String regex = substring + "\\s*\\(";
+ return input.matches(".*" + regex + ".*");
+ }
+
+
+ /**
+ * Method to find method calls that need to be wrapped
+ */
+ private @Nullable M visitMethodCall(M methodCall, Supplier visitSuper) {
+ if (!methodMatcher.matches(methodCall)) {
+ if (!excludeOwner) {
+ // Make no changes
+ return visitSuper.get();
+ }
+ if (!containsSubstringWithParenthesis(methodCall.toString(), methodPattern.replaceAll("\\(.*?\\)", "").
+ replaceAll("\\*", "").trim().split(" ")[1])){
+ // Make no changes
+ return visitSuper.get();
+ }
+ }
+ // If match found, check that it is not already handled by a try block
+ try {
+ // Get the first upstream try block. Will throw exception if there are none
+ J.Try _try = getCursor().dropParentUntil(it -> it instanceof J.Try).getValue();
+
+ // Get the first enclosing block
+ J.Block block = getCursor().dropParentUntil(it -> it instanceof J.Block).getValue();
+
+ // Check to see if this try block is the parent of the enclosing block
+ if (_try.getBody().equals(block)) {
+ // Check if the correct exception is caught
+ boolean isCaught = _try.getCatches().stream().anyMatch(
+ _catch -> Objects.requireNonNull(_catch.getParameter().getType())
+ .isAssignableFrom(Pattern.compile(fullyQualifiedExceptionName)));
+
+ // Make no changes if exception already caught
+ if (isCaught) {
+ return visitSuper.get();
+ }
+ }
+ } catch (IllegalStateException ignored) {}
+ // If the method matches and exception is not caught set messages for block
+ getCursor().putMessageOnFirstEnclosing(J.Block.class, "METHOD", methodCall);
+
+ Tree parent = getCursor().getParentTreeCursor().getValue();
+ if (! (parent instanceof J.Block)) {
+ // If the method is part of a nested statement flag the direct tree parent
+ getCursor().putMessageOnFirstEnclosing(J.Block.class, "PARENT", parent);
+ try {
+ // And the first parent that is a statement
+ Statement statement = getCursor().dropParentUntil(it -> it instanceof Statement).getValue();
+ getCursor().putMessageOnFirstEnclosing(J.Block.class, "STATEMENT", statement);
+ } catch (IllegalStateException ignored) {}
+ }
+
+ return visitSuper.get();
+ }
+
+ /**
+ * The Suppliers that traverse the LST and redirect all types of method calls through visitMethodCall.
+ */
+
+ @Override
+ public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext context) {
+ return visitMethodCall(newClass, () -> super.visitNewClass(newClass, context));
+ }
+
+ @Override
+ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext context) {
+ return visitMethodCall(method, () -> super.visitMethodInvocation(method, context));
+ }
+
+ @Override
+ public J.MemberReference visitMemberReference(J.MemberReference memberRef, ExecutionContext context) {
+ return visitMethodCall(memberRef, () -> super.visitMemberReference(memberRef, context));
+ }
+
+ } // end catchUncheckedVisitor
+
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/RemoveFixedDelayRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/RemoveFixedDelayRecipe.java
new file mode 100644
index 0000000000000..8009eca8f1672
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/RemoveFixedDelayRecipe.java
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+
+/**
+ * RemoveFixedDelayRecipe removes any leftover imports for FixedDelayOptions
+ * and any variables declared with the FixedDelayOptions type.
+ * --------------------------------------------------
+ * Removes code such as:
+ * import com.azure.core.http.policy.FixedDelayOptions;
+ * ...
+ * FixedDelayOptions s;
+ * --------------------------------------------------
+ */
+public class RemoveFixedDelayRecipe extends Recipe {
+ /**
+ * Method to return a simple short description of RemoveFixedDelayRecipe
+ * @return A simple short description/name of the recipe
+ */
+ @Override
+ public String getDisplayName() {
+ return "Removes imports and variable declarations for FixedDelayOptions";
+ }
+ /**
+ * Method to return a description of RemoveFixedDelayRecipe
+ * @return A short description of the recipe
+ */
+ @Override
+ public String getDescription() {
+ return "This recipe removes any leftover imports and variables using FixedDelayOptions.";
+ }
+ /**
+ * Method to return the visitor that visits the usages of FixedDelayOptions
+ * @return A TreeVisitor to visit the usages of FixedDelayOptions
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new FixedDelayVisitor();
+ }
+ /**
+ * Visitor to remove FixedDelayOptions
+ */
+ private static class FixedDelayVisitor extends JavaIsoVisitor {
+ /**
+ * Method to remove unnecessary import for FixedDelay
+ */
+ @Override
+ public J.Import visitImport(J.Import _import, ExecutionContext executionContext) {
+ J.Import visitedImport = super.visitImport(_import, executionContext);
+ if (visitedImport.getQualid() != null){
+ if (visitedImport.getQualid().getSimpleName().contains("FixedDelay")){
+ return null;
+ }
+ }
+ return visitedImport;
+ }
+ /**
+ * Method to remove unnecessary variable declarations for FixedDelay
+ */
+ @Override
+ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext executionContext) {
+ J.VariableDeclarations visitedVar = super.visitVariableDeclarations(multiVariable, executionContext);
+ if (visitedVar.getTypeExpression() == null) {
+ return visitedVar;
+ }
+ if (visitedVar.getTypeExpression().toString().contains("FixedDelayOptions")) {
+ // Return null to remove the block
+ return null;
+ }
+ return visitedVar;
+ }
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/TypeReferenceRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/TypeReferenceRecipe.java
new file mode 100644
index 0000000000000..a927f8626026e
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/TypeReferenceRecipe.java
@@ -0,0 +1,236 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite;
+
+import org.openrewrite.Cursor;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.JavaTemplate;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.JavaType;
+import org.openrewrite.java.tree.TypeTree;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Recipe to convert TypeReference to ParameterizedType and remove TypeReference import statements.
+ * --------------------------------------------------
+ * Before applying this recipe:
+ * import com.azure.core.util.serializer.TypeReference;
+ * ...
+ * result = binaryDataResponse.getValue().toObject(new TypeReference>() { });
+ * --------------------------------------------------
+ * After applying this recipe:
+ * import java.lang.reflect.ParameterizedType;
+ * import java.lang.reflect.Type;
+ * ...
+ result = binaryDataResponse.getValue().toObject(new ParameterizedType() {
+ @Override
+ public Type getRawType() {
+ return List.class;
+ }
+
+ @Override
+ public Type[] getActualTypeArguments() {
+ return new Type[]{TranslatedTextItem.class};
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return null;
+ }
+ });
+ * --------------------------------------------------
+ */
+public class TypeReferenceRecipe extends Recipe {
+
+ @Override
+ public String getDisplayName() {
+ return "Convert TypeReference to ParameterizedType and remove imports";
+ }
+
+ @Override
+ public String getDescription() {
+ return "This recipe converts TypeReference<> to ParameterizedType and removes the import statement for TypeReference.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new ConvertTypeReferenceVisitor();
+ }
+
+ private static class ConvertTypeReferenceVisitor extends JavaIsoVisitor {
+ /**
+ * Method to visit instantiation of TypeReference and replace it with ParameterizedType
+ * instantiation including override methods.
+ * */
+ @Override
+ public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext ctx) {
+ J.NewClass visitedNewClass = super.visitNewClass(newClass, ctx);
+
+ // Check if the TypeReference reference has already been transformed
+ if (visitedNewClass.getBody() == null){return visitedNewClass;}
+ boolean alreadyTransformed = visitedNewClass.getBody().getStatements().stream()
+ .filter(statement -> statement instanceof J.MethodDeclaration)
+ .map(J.MethodDeclaration.class::cast)
+ .anyMatch(methodDeclaration -> methodDeclaration.getName().getSimpleName().equals("getRawType"));
+ if (visitedNewClass.getClazz() == null){return visitedNewClass;}
+ if (!alreadyTransformed && visitedNewClass.getClazz().toString().contains("TypeReference")) {
+ // Extract type from generic type in TypeReference declaration
+ String genType = null;
+ String type = null;
+ String type2 = null;
+ List fullType = null;
+
+
+ if(visitedNewClass.getClazz().getType() != null){
+ try {
+ fullType = ((JavaType.Parameterized) visitedNewClass.getClazz().getType()).getTypeParameters();
+ if (fullType.get(0) instanceof JavaType.Parameterized) { // Check if using parameterized type
+ type = ((JavaType.Class)((JavaType.Parameterized) fullType.get(0)).getTypeParameters().get(0)).getClassName();
+ if (((JavaType.Parameterized) fullType.get(0)).getTypeParameters().size() > 1) {
+ type2 = ((JavaType.Class)((JavaType.Parameterized) fullType.get(0)).getTypeParameters().get(1)).getClassName();
+ }
+ genType = ((JavaType.Parameterized) fullType.get(0)).getClassName();
+ } else {
+ genType = ((JavaType.Class)fullType.get(0)).getClassName();
+ }
+ } catch (ClassCastException e) { // OpenRewrite has a bug where parameterized new-classes contained in method arguments can't be parsed, so extract type information using String manipulation instead
+ genType = visitedNewClass.getClazz().toString().split("<")[1];
+ if (visitedNewClass.getClazz().toString().contains(",")) {
+ type = visitedNewClass.getClazz().toString().split("<")[2].replace(">", "").split(",")[0];
+ type2 = visitedNewClass.getClazz().toString().split("<")[2].replace(">", "").split(",")[1];
+ }else {
+ type = visitedNewClass.getClazz().toString().split("<")[2].replace(">", "");
+ }
+ }
+ }
+ JavaTemplate methodRawTypeTemplate = JavaTemplate.builder("@Override public Type getRawType() { return " + extractTypeArgument(visitedNewClass.toString()) + ".class; }").build();
+ if (genType!=null){
+ methodRawTypeTemplate = JavaTemplate.builder("@Override public Type getRawType() { return " + genType + ".class; }").build();
+ }
+ JavaTemplate methodActualTypeTemplate = JavaTemplate.builder("@Override public Type[] getActualTypeArguments() { return new Type[] {}; }").build();
+ if (type != null){
+ methodActualTypeTemplate = JavaTemplate.builder("@Override public Type[] getActualTypeArguments() { return new Type[] { " + type + ".class }; }").build();
+ }
+ JavaTemplate methodOwnerTypeTemplate = JavaTemplate.builder("@Override public Type getOwnerType() { return null; }").build();
+ if (type2 != null){ // If TypeReference uses Map or any other class with the same structure like Foo
+ methodActualTypeTemplate = JavaTemplate.builder("@Override public Type[] getActualTypeArguments() { return new Type[] { " + type + ".class," + type2 + ".class }; }").build();
+ }
+ // Apply Templates (add methods to body)
+
+ visitedNewClass = visitedNewClass.withBody(methodRawTypeTemplate.apply(new Cursor(getCursor(), visitedNewClass.getBody()),
+ visitedNewClass.getBody().getCoordinates().lastStatement()));
+ visitedNewClass = visitedNewClass.withBody(methodActualTypeTemplate.apply(new Cursor(getCursor(), visitedNewClass.getBody()),
+ visitedNewClass.getBody().getCoordinates().lastStatement()));
+ visitedNewClass = visitedNewClass.withBody(methodOwnerTypeTemplate.apply(new Cursor(getCursor(), visitedNewClass.getBody()),
+ visitedNewClass.getBody().getCoordinates().lastStatement()));
+
+ visitedNewClass = visitedNewClass.withClazz(TypeTree.build(" ParameterizedType")); // Replace TypeReference with Type
+
+ }
+ return visitedNewClass;
+ }
+
+ private final Set importSet = new HashSet<>();
+
+ @Override
+ public J.Import visitImport(J.Import importStmt, ExecutionContext ctx) {
+ String importQualid = importStmt.getQualid().toString();
+
+ // Add the import to the set and check if it already exists
+ boolean isNewImport = importSet.add(importQualid);
+
+ // If the import is for ParameterizedType, and it's already in the set, skip it
+ if (importQualid.trim().equals("java.lang.reflect.ParameterizedType") && !isNewImport) {
+ return null;
+ }
+
+ // Remove the import statement for TypeReference and add import for ParameterizedType
+ if (importQualid.equals("com.azure.core.util.serializer.TypeReference")) {
+ importSet.add("java.lang.reflect.ParameterizedType");
+ return importStmt.withQualid(TypeTree.build(" java.lang.reflect.ParameterizedType"));
+ }
+
+ // Change BinaryData import to a new package
+ if (importQualid.equals("com.azure.core.util.BinaryData")) {
+ importSet.add("io.clientcore.core.util.binarydata.BinaryData");
+ return importStmt.withQualid(TypeTree.build(" io.clientcore.core.util.binarydata.BinaryData"));
+ }
+
+ // Return other imports normally
+ return importStmt;
+ }
+ /**
+ * Method to visit variable declaration for TypeReference and make sure it is converted to java.lang.reflect.Type
+ */
+ @Override
+ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext executionContext) {
+ J.VariableDeclarations visitedDeclarations = super.visitVariableDeclarations(multiVariable, executionContext);
+ if (visitedDeclarations.toString().contains("TypeReference")
+ && visitedDeclarations.toString().contains("ParameterizedType")) {
+ visitedDeclarations = visitedDeclarations.withTypeExpression(TypeTree.build(" Type"));
+ return visitedDeclarations;
+ }
+ return visitedDeclarations;
+ }
+
+ /**
+ * Method to visit BinaryData type and change it to the new version
+ */
+ @Override
+ public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
+ J.FieldAccess fa = super.visitFieldAccess(fieldAccess, ctx);
+ String fullyQualified = fa.getTarget() + "." + fa.getSimpleName();
+ if (fullyQualified.equals("com.azure.core.util.BinaryData")) {
+ return TypeTree.build(" io.clientcore.core.util.binarydata.BinaryData");
+ }
+ return fa;
+ }
+
+ /**
+ * Method to add import for java.lang.reflect.Type if needed
+ */
+ @Override
+ public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext executionContext) {
+ J.CompilationUnit visitedCompilationUnit = super.visitCompilationUnit(cu, executionContext);
+ J.Import newImport = null;
+ boolean addTypeImport = false;
+ if (visitedCompilationUnit.getImports().isEmpty()){return visitedCompilationUnit;}
+ for (J.Import i : visitedCompilationUnit.getImports()) {
+ newImport = i;
+ if (i.toString().contains("java.lang.reflect.Type")){
+ return visitedCompilationUnit;
+ }
+ if (i.toString().contains("java.lang.reflect.ParameterizedType")){
+ addTypeImport = true;
+ }
+ }
+ if (addTypeImport) {
+ newImport = newImport.withQualid(TypeTree.build(" java.lang.reflect.Type"));
+ List imports = visitedCompilationUnit.getImports();
+ imports.add(newImport);
+ return visitedCompilationUnit.withImports(imports);
+ }
+ return visitedCompilationUnit;
+ }
+
+ public String extractTypeArgument(String text) {
+ // Find the start and end of the type argument
+ int startIndex = text.indexOf('<');
+ int endIndex = text.indexOf('>', startIndex);
+
+ if (startIndex == -1 || endIndex == -1) {
+ return null; // If '<' or '>' not found, return null
+ }
+
+ // Extract the substring between the angle brackets
+ return text.substring(startIndex + 1, endIndex).trim();
+ }
+ }
+
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ContextRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ContextRecipe.java
new file mode 100644
index 0000000000000..44c7ce408ef36
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ContextRecipe.java
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.clientcore;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeTree;
+
+/**
+ * ContextRecipe changes all instances of Context.NONE (from azure core v1) to Context.none() (from azure core v2).
+ * This recipe also updates the import statements for the aforementioned class.
+ * --------------------------------------------------
+ * Before applying this recipe:
+ * import com.azure.core.util.Context;
+ * com.azure.core.http.rest.RequestOptions;
+ * ...
+ * public void context(){ print(Context.NONE); }
+ * --------------------------------------------------
+ * After applying this recipe:
+ * import io.clientcore.core.util.Context;
+ * io.clientcore.core.http.models.RequestOptions
+ * ...
+ * public void context(){ print(Context.none()); }
+ * --------------------------------------------------
+ */
+public class ContextRecipe extends Recipe {
+ /**
+ * Method to return a simple short description of ContextRecipe
+ * @return A simple short description/name of the recipe
+ */
+ @Override
+ public String getDisplayName() {
+ return "Change static field 'Context.NONE' to Method 'Context.none()'";
+ }
+ /**
+ * Method to return a description of ContextRecipe
+ * @return A short description of the recipe
+ */
+ @Override
+ public String getDescription() {
+ return "This recipe changes any calls to Context.NONE to Context.none().\n" +
+ "It also changes the import statement of com.azure.core.util.Context to io.clientcore.core.util.Context.";
+ }
+ /**
+ * Method to return the visitor that visits the Context.NONE identifier
+ * @return A TreeVisitor to visit the NONE identifier and change it to none()
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new ChangeStaticFieldToMethodVisitor();
+ }
+ /**
+ * Visitor to change NONE identifier to none()
+ */
+ private static class ChangeStaticFieldToMethodVisitor extends JavaIsoVisitor {
+ /**
+ * Method to change com.azure.core.util.Context to io.clientcore.core.util.Context
+ */
+ @Override
+ public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
+ J.FieldAccess visitedFieldAccess = super.visitFieldAccess(fieldAccess, ctx);
+ String fullyQualified = visitedFieldAccess.getTarget() + "." + visitedFieldAccess.getSimpleName();
+ if (fullyQualified.equals("com.azure.core.http.rest.RequestOptions")) {
+ return TypeTree.build(" io.clientcore.core.http.models.RequestOptions");
+ }
+ if (fullyQualified.equals("com.azure.core.util.Context")) {
+ return TypeTree.build(" io.clientcore.core.util.Context");
+ }
+ if (fullyQualified.equals("Context.NONE")){
+ return TypeTree.build("Context.none()");
+ }
+ return visitedFieldAccess;
+ }
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/HttpLogOptionsRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/HttpLogOptionsRecipe.java
new file mode 100644
index 0000000000000..068653848998d
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/HttpLogOptionsRecipe.java
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.clientcore;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeTree;
+
+/**
+ * HttpLogOptionsRecipe change usage of the com.azure.core.http.policy.HttpLogDetailLevel while also changing
+ * the com.azure.core.http.policy.HttpLogOptions Type.
+ * The import statements are also updated.
+ * Changes:
+ * com.azure.core.http.policy.HttpLogDetailLevel -> io.clientcore.core.http.models.HttpLogOptions.HttpLogDetailLevel
+ * com.azure.core.http.policy.HttpLogOptions -> io.clientcore.core.http.models.HttpLogOptions
+ * --------------------------------------------------
+ * Before applying this recipe:
+ * import com.azure.core.http.policy.HttpLogDetailLevel;
+ * import com.azure.core.http.policy.HttpLogOptions;
+ * ...
+ * public void logOptions(){ print(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)); }
+ * --------------------------------------------------
+ * After applying this recipe:
+ * import io.clientcore.core.http.models.HttpLogOptions;
+ * ...
+ * public void logOptions(){ print(new HttpLogOptions().setLogLevel(HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS)); }
+ * --------------------------------------------------
+ */
+public class HttpLogOptionsRecipe extends Recipe {
+ /**
+ * Method to return a simple short description of HttpLogOptionsRecipe
+ * @return A simple short description/name of the recipe
+ */
+ @Override
+ public String getDisplayName() {
+ return "Migrate the HttpLogOptions and HttpLogDetail usages";
+ }
+ /**
+ * Method to return a description of HttpLogOptionsRecipe
+ * @return A short description of the recipe
+ */
+ @Override
+ public String getDescription() {
+ return "This recipe changes any usages of HttpLogOptions from azure core v1 to its respective type from azure core v2.\n" +
+ "It also migrates any usages of HttpLogDetailLevel to azure core v2.";
+ }
+ /**
+ * Method to return the visitor that visits the usages of HttpLogOptions and HttpLogDetailLevel
+ * @return A TreeVisitor to visit the usages of HttpLogOptions and HttpLogDetailLevel
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new HttpLogOptionsVisitor();
+ }
+ /**
+ * Visitor to change HttpLogOptions type and change usage of HttpLogDetailLevel
+ */
+ private static class HttpLogOptionsVisitor extends JavaIsoVisitor {
+ /**
+ * Method to change usage of the HttpLogDetailLevel while also changing the HttpLogOptions Type
+ */
+ @Override
+ public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
+ J.FieldAccess visitedFieldAccess = super.visitFieldAccess(fieldAccess, ctx);
+ String fullyQualified = visitedFieldAccess.getTarget() + "." + visitedFieldAccess.getSimpleName();
+ if (fullyQualified.equals("com.azure.core.http.policy.HttpLogOptions")) {
+ return TypeTree.build(" io.clientcore.core.http.models.HttpLogOptions");
+ }
+ if (fullyQualified.equals("com.azure.core.http.policy.HttpLogDetailLevel") &&
+ visitedFieldAccess.getSimpleName().equals("HttpLogDetailLevel") &&
+ visitedFieldAccess.print().contains("com.azure")){
+ return TypeTree.build(" io.clientcore.core.http.models.HttpLogOptions.HttpLogDetailLevel");
+ }
+ return visitedFieldAccess;
+ }
+ /**
+ * Method to remove unnecessary import fo HttpLogDetailLevel as the class is already included in client-core HttpLogOptions class
+ */
+ @Override
+ public J.Import visitImport(J.Import _import, ExecutionContext executionContext) {
+ J.Import visitedImport = super.visitImport(_import, executionContext);
+ if (visitedImport.getQualid().getSimpleName().contains("HttpLogDetailLevel")){
+ return null;
+ }
+ return visitedImport;
+ }
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ResponseRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ResponseRecipe.java
new file mode 100644
index 0000000000000..a1ca8aa50ce6f
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/ResponseRecipe.java
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.clientcore;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeTree;
+
+/**
+ * ResponseRecipe changes all instances of Response (from azure core v1) to Response (from azure core v2).
+ * This recipe also updates the import statements for the aforementioned class.
+ * --------------------------------------------------
+ * Before applying this recipe:
+ * import com.azure.core.http.rest.Response;
+ * --------------------------------------------------
+ * After applying this recipe:
+ * import io.clientcore.core.http.models.Response;
+ * --------------------------------------------------
+ */
+public class ResponseRecipe extends Recipe {
+ /**
+ * Method to return a simple short description of ResponseRecipe
+ * @return A simple short description/name of the recipe
+ */
+ @Override
+ public String getDisplayName() {
+ return "Update Response type to v2 version";
+ }
+ /**
+ * Method to return a description of ResponseRecipe
+ * @return A short description of the recipe
+ */
+ @Override
+ public String getDescription() {
+ return "This recipe changes com.azure.core.http.rest.Response to io.clientcore.core.http.models.Response.";
+ }
+ /**
+ * Method to return the visitor that visits the Response class
+ * @return A TreeVisitor to visit the Response class and update it
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new UpdateResponseVisitor();
+ }
+ /**
+ * Visitor to update Response
+ */
+ private static class UpdateResponseVisitor extends JavaIsoVisitor {
+ /**
+ * Method to change com.azure.core.http.rest.Response to io.clientcore.core.http.models.Response
+ */
+ @Override
+ public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
+ J.FieldAccess visitedFieldAccess = super.visitFieldAccess(fieldAccess, ctx);
+ String fullyQualified = visitedFieldAccess.getTarget() + "." + visitedFieldAccess.getSimpleName();
+ if (fullyQualified.equals("com.azure.core.http.rest.Response")) {
+ return TypeTree.build(" io.clientcore.core.http.models.Response");
+ }
+ return visitedFieldAccess;
+ }
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/RetryOptionsConstructorRecipe.java b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/RetryOptionsConstructorRecipe.java
new file mode 100644
index 0000000000000..079b4663d75a8
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/java/com/azure/openrewrite/clientcore/RetryOptionsConstructorRecipe.java
@@ -0,0 +1,155 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.clientcore;
+
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.Expression;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.TypeTree;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+/**
+ * RetryOptionsRecipe changes RetryOptions constructor to HttpRetryOptions constructor.
+ * It also removes any references to FixedDelay and ExponentialDelay and changes
+ * com.azure.core.http.policy.RetryOptions to io.clientcore.core.http.models.HttpRetryOptions
+ * --------------------------------------------------
+ * Before applying this recipe:
+ * import com.azure.core.http.policy.RetryOptions;
+ * ...
+ * new RetryOptions(new FixedDelayOptions(3, Duration.ofMillis(50)))
+ * --------------------------------------------------
+ * After applying this recipe:
+ * import io.clientcore.core.http.models.HttpRetryOptions;
+ * ...
+ * new HttpRetryOptions(3, Duration.ofMillis(50))
+ * --------------------------------------------------
+ */
+public class RetryOptionsConstructorRecipe extends Recipe {
+ /**
+ * Method to return a simple short description of RetryOptionsRecipe
+ * @return A simple short description/name of the recipe
+ */
+ @Override
+ public String getDisplayName() {
+ return "Change RetryOptions constructor";
+ }
+ /**
+ * Method to return a description of RetryOptionsRecipe
+ * @return A short description of the recipe
+ */
+ @Override
+ public String getDescription() {
+ return "This recipe changes the constructor for RetryOptions to HttpRetryOptions.\n" +
+ "This includes removing any references to FixedDelay and ExponentialDelay and changing\n" +
+ " * com.azure.core.http.policy.RetryOptions to io.clientcore.core.http.models.HttpRetryOptions.";
+ }
+ /**
+ * Method to return the visitor that changes RetryOptions constructor to HttpRetryOptions constructor
+ * @return A TreeVisitor to change RetryOptions constructor to HttpRetryOptions constructor
+ */
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new RetryVisitor();
+ }
+ /**
+ * Visitor to change RetryOptions constructor to HttpRetryOptions constructor
+ */
+ private static class RetryVisitor extends JavaIsoVisitor {
+
+ private final Map> variableToArgsMap = new HashMap<>();
+
+ /**
+ * Method to visit variable declaration for FixedDelay or ExponentialDelay
+ */
+ @Override
+ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations variableDeclarations, ExecutionContext executionContext) {
+ J.VariableDeclarations vd = super.visitVariableDeclarations(variableDeclarations, executionContext);
+ for (J.VariableDeclarations.NamedVariable variable : vd.getVariables()) {
+ J.NewClass newClass = null;
+ try {
+ newClass = (J.NewClass) variable.getInitializer();
+ } catch (Exception e) {
+ return vd;
+ }
+ if (newClass != null) {
+ if (newClass.getType() != null) {
+ String className = newClass.getType().toString();
+ if (className.contains("FixedDelayOptions") || className.contains("ExponentialDelayOptions")) {
+ List args = new ArrayList<>(newClass.getArguments());
+ variableToArgsMap.put(variable.getSimpleName(), args);
+ }
+ }
+ }
+ }
+ return vd;
+ }
+
+ /**
+ * Method to visit constructor for RetryOptions
+ */
+ @Override
+ public J.NewClass visitNewClass(J.NewClass newClass, ExecutionContext executionContext) {
+ J.NewClass visitedNewClass = super.visitNewClass(newClass, executionContext);
+ if (visitedNewClass.toString().contains("new HttpRetryOptions")) {
+ if (visitedNewClass.getArguments().size() == 1) {
+ Expression constructorArg = visitedNewClass.getArguments().get(0);
+ if (constructorArg instanceof J.Identifier) {
+ String variableName = ((J.Identifier) constructorArg).getSimpleName();
+ List args = variableToArgsMap.get(variableName);
+ if (args != null) {
+ return visitedNewClass.withArguments(args);
+ }
+ } else if (constructorArg instanceof J.NewClass) {
+ J.NewClass newArg = (J.NewClass) constructorArg;
+ List args = new ArrayList<>(newArg.getArguments());
+ return visitedNewClass.withArguments(args);
+ }
+ }
+ }
+ return visitedNewClass;
+ }
+
+ /**
+ * Method to change RetryOptions to HttpRetryOptions
+ */
+ @Override
+ public J.Identifier visitIdentifier(J.Identifier identifier, ExecutionContext ctx) {
+ J.Identifier visitedIdentifier = super.visitIdentifier(identifier, ctx);
+ if (visitedIdentifier.getSimpleName().equals("RetryOptions")) {
+ return visitedIdentifier.withSimpleName("HttpRetryOptions");
+ }
+ return visitedIdentifier;
+ }
+
+ /**
+ * Method to change import to HttpRetryOptions
+ */
+ @Override
+ public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, ExecutionContext ctx) {
+ J.FieldAccess visitedFieldAccess = super.visitFieldAccess(fieldAccess, ctx);
+ String fullyQualified = visitedFieldAccess.getTarget() + "." + visitedFieldAccess.getSimpleName();
+ if (fullyQualified.equals("com.azure.core.http.policy.HttpRetryOptions")) {
+ return TypeTree.build(" io.clientcore.core.http.models.HttpRetryOptions");
+ }
+ return visitedFieldAccess;
+ }
+
+ /**
+ * Method to change usages of retryOptions builder method to httpRetryOptions
+ */
+ @Override
+ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) {
+ J.MethodInvocation visitedMethodInv = super.visitMethodInvocation(method, executionContext);
+ if (visitedMethodInv.getSimpleName().equals("retryOptions")) {
+ return visitedMethodInv.withName(visitedMethodInv.getName().withSimpleName("httpRetryOptions"));
+ }
+ return visitedMethodInv;
+ }
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/main/resources/META-INF/rewrite/rewrite.yml b/sdk/tools/azure-openrewrite/src/main/resources/META-INF/rewrite/rewrite.yml
new file mode 100644
index 0000000000000..0d18f42a84624
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/main/resources/META-INF/rewrite/rewrite.yml
@@ -0,0 +1,258 @@
+type: specs.openrewrite.org/v1beta/recipe
+name: com.azure.openrewrite.migrateToVNext
+displayName: Migrate from azure-core to azure-core-v2
+description: This recipe migrates the azure sdk libraries from azure-core to azure-core-v2 and clientcore libraries.
+recipeList:
+ # ----------------------------------
+ #
+ # Java-Based LST Replacement Recipes
+ #
+ # ----------------------------------
+
+ # Recipe that changes all instances of com.azure.core.http.HttpHeaderName
+ # to io.clientcore.core.http.models.HttpHeaderName
+ # Before:
+ # import com.azure.core.http.HttpHeaderName;
+ # After:
+ # import io.clientcore.core.http.models.HttpHeaderName;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.http.HttpHeaderName
+ newFullyQualifiedTypeName: io.clientcore.core.http.models.HttpHeaderName
+
+ # Recipe that changes all instances of com.azure.core.util.logging.ClientLogger
+ # to io.clientcore.core.util.ClientLogger
+ # Before:
+ # import com.azure.core.util.logging.ClientLogger;
+ # After:
+ # import io.clientcore.core.util.ClientLogger;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.util.logging.ClientLogger
+ newFullyQualifiedTypeName: io.clientcore.core.util.ClientLogger
+
+ # Recipe that changes all instances of com.azure.core.util.CoreUtils
+ # to com.azure.core.v2.util.CoreUtils
+ # Before:
+ # import com.azure.core.util.CoreUtils;
+ # After:
+ # import com.azure.core.v2.util.CoreUtils;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.util.CoreUtils
+ newFullyQualifiedTypeName: com.azure.core.v2.util.CoreUtils
+
+ # Recipe that changes all instances of com.azure.core.http.policy.KeyCredentialPolicy
+ # to io.clientcore.core.http.pipeline.KeyCredentialPolicy
+ # Before:
+ # import com.azure.core.http.policy.KeyCredentialPolicy;
+ # After:
+ # import io.clientcore.core.http.pipeline.KeyCredentialPolicy;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.http.policy.KeyCredentialPolicy
+ newFullyQualifiedTypeName: io.clientcore.core.http.pipeline.KeyCredentialPolicy
+
+ # Recipe that changes all instances of com.azure.core.credential.KeyCredential
+ # to io.clientcore.core.credential.KeyCredential
+ # Before:
+ # import com.azure.core.credential.KeyCredential;
+ # After:
+ # import io.clientcore.core.credential.KeyCredential;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.credential.KeyCredential
+ newFullyQualifiedTypeName: io.clientcore.core.credential.KeyCredential
+
+ # Recipe that changes all instances of com.azure.core.client.traits.KeyCredentialTrait
+ # to io.clientcore.core.models.traits.KeyCredentialTrait
+ # Before:
+ # import com.azure.core.client.traits.KeyCredentialTrait;
+ # After:
+ # import io.clientcore.core.models.traits.KeyCredentialTrait;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.client.traits.KeyCredentialTrait
+ newFullyQualifiedTypeName: io.clientcore.core.models.traits.KeyCredentialTrait
+
+ # NOTE:
+ # A copy of the client-core jar file must be in the resources\classpath
+ # directory to reliably parse from clientcore library
+
+ # --------------------------------------------------------------------
+ # Recipes to migrate TextTranslationClientBuilder HttpTrait implemented
+ # methods and parameters
+ # --------------------------------------------------------------------
+ # Change Types from the azure-core to clientcore versions
+ # Before:
+ # import com.azure.core.http.HttpClient;
+ # After:
+ # import io.clientcore.core.http.client.HttpClient;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.http.HttpClient
+ newFullyQualifiedTypeName: io.clientcore.core.http.client.HttpClient
+ ignoreDefinition: false
+ # Before:
+ # import com.azure.core.http.HttpPipeline;
+ # After:
+ # import io.clientcore.core.http.pipeline.HttpPipeline;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.http.HttpPipeline
+ newFullyQualifiedTypeName: io.clientcore.core.http.pipeline.HttpPipeline
+ ignoreDefinition: false
+ # Before:
+ # import com.azure.core.http.policy.HttpPipelinePolicy;
+ # After:
+ # import io.clientcore.core.http.pipeline.HttpPipelinePolicy;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.http.policy.HttpPipelinePolicy
+ newFullyQualifiedTypeName: io.clientcore.core.http.pipeline.HttpPipelinePolicy
+ ignoreDefinition: false
+
+ # Rename methods
+ # Alternatively, can target HttpTrait directly
+
+ # Before:
+ # textTranslationClient.retryOptions(new RetryOptions())
+ # After:
+ # textTranslationClient.httpRetryOptions(new RetryOptions())
+ - org.openrewrite.java.ChangeMethodName:
+ methodPattern: com.azure.ai.translation.text.TextTranslationClientBuilder retryOptions(..)
+ newMethodName: httpRetryOptions
+ matchOverrides: true
+ # Before:
+ # textTranslationClient.pipeline(pipeline)
+ # After:
+ # textTranslationClient.httpPipeline(pipeline)
+ - org.openrewrite.java.ChangeMethodName:
+ methodPattern: com.azure.ai.translation.text.TextTranslationClientBuilder pipeline(..)
+ newMethodName: httpPipeline
+ matchOverrides: true
+ # Before:
+ # textTranslationClient.addPolicy(customPolicy)
+ # After:
+ # textTranslationClient.addHttpPipelinePolicy(customPolicy)
+ - org.openrewrite.java.ChangeMethodName:
+ methodPattern: com.azure.ai.translation.text.TextTranslationClientBuilder addPolicy(..)
+ newMethodName: addHttpPipelinePolicy
+ matchOverrides: true
+ # End TextTranslationClientBuilder - HttpTrait implementation recipes
+
+ # Recipe to change com.azure.core.credential package name to io.clientcore.core.credential
+ # Before:
+ # import com.azure.core.credential.*;
+ # After:
+ # import io.clientcore.core.credential.*;
+ - org.openrewrite.java.ChangePackage:
+ oldPackageName: com.azure.core.credential
+ newPackageName: io.clientcore.core.credential
+
+ # Recipes that update all instances of azure-core exceptions where
+ # use is equivalent and type/name change is sufficient/safe.
+ # Update to azure-core-v2 version
+ # Before:
+ # import com.azure.core.exception.ClientAuthenticationException;
+ # After:
+ # import com.azure.core.v2.exception.ClientAuthenticationException;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.exception.ClientAuthenticationException
+ newFullyQualifiedTypeName: com.azure.core.v2.exception.ClientAuthenticationException
+ # Before:
+ # import com.azure.core.exception.ResourceModifiedException;
+ # After:
+ # import com.azure.core.v2.exception.ResourceModifiedException;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.exception.ResourceModifiedException
+ newFullyQualifiedTypeName: com.azure.core.v2.exception.ResourceModifiedException
+ # Before:
+ # import com.azure.core.exception.ResourceNotFoundException;
+ # After:
+ # import com.azure.core.v2.exception.ResourceNotFoundException;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.exception.ResourceNotFoundException
+ newFullyQualifiedTypeName: com.azure.core.v2.exception.ResourceNotFoundException
+ # Update to clientcore version
+ # Before:
+ # import com.azure.core.exception.HttpResponseException;
+ # After:
+ # import io.clientcore.core.http.exception.HttpResponseException;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.exception.HttpResponseException
+ newFullyQualifiedTypeName: io.clientcore.core.http.exception.HttpResponseException
+ # End azure-core-exception change type Recipes
+
+ # Recipe that changes all instances of com.azure.core.util.Configuration
+ # to io.clientcore.core.util.configuration.Configuration
+ # Before:
+ # import com.azure.core.util.Configuration;
+ # After:
+ # import io.clientcore.core.util.configuration.Configuration;
+ - org.openrewrite.java.ChangeType:
+ oldFullyQualifiedTypeName: com.azure.core.util.Configuration
+ newFullyQualifiedTypeName: io.clientcore.core.util.configuration.Configuration
+
+ # azure-core v2 BinaryData.toObject throws an IOException. This recipe encloses all calls in
+ # a try-catch block.
+ # Before:
+ # List result = binaryDataResponse.getValue().toObject( /* Any Args */);
+ # After:
+ # List result = null;
+ # try {
+ # result = binaryDataResponse.getValue().toObject( /* Any Args */);
+ # } catch (IOException e) {
+ # e.printStackTrace();
+ # }
+ #
+ # NOTE: Tests are failing, so I'm disabling this recipe for now.
+ # WARNING: This recipe MUST be run before com.azure.openrewrite.TypeReferenceRecipe.
+ #- com.azure.openrewrite.AddTryCatchToMethodCallRecipe:
+ # methodPattern: com.azure.core.util.BinaryData toObject(..)
+ # catchTemplateString: catch (IOException e) { e.printStackTrace(); }
+ # fullyQualifiedExceptionName: java.io.IOException
+ # excludeOwner: true
+
+ # azure-core v2 TextTranslationClient.translate throws an IOException. This recipe encloses all calls in
+ # a try-catch block.
+ # Before:
+ # List result = textTranslationClient.translate( /* Any Args */);
+ # After:
+ # List result = null;
+ # try {
+ # result = textTranslationClient.translate( /* Any Args */);
+ # } catch (IOException e) {
+ # throw new RuntimeException(e);
+ # }
+ # NOTE: Tests are failing, so I'm disabling this recipe for now.
+ #- com.azure.openrewrite.AddTryCatchToMethodCallRecipe:
+ # methodPattern: com.azure.ai.translation.text.TextTranslationClient translate(..)
+ # catchTemplateString: catch (IOException e) { throw new RuntimeException(e); }
+ # fullyQualifiedExceptionName: java.io.IOException
+ # excludeOwner: true
+
+ - com.azure.openrewrite.clientcore.ResponseRecipe
+ - com.azure.openrewrite.clientcore.ContextRecipe
+ - com.azure.openrewrite.clientcore.RetryOptionsConstructorRecipe
+ - com.azure.openrewrite.TypeReferenceRecipe
+ - com.azure.openrewrite.clientcore.HttpLogOptionsRecipe
+ - com.azure.openrewrite.RemoveFixedDelayRecipe
+
+ # Recipe to re-order imports to match standard conventions
+ - org.openrewrite.java.OrderImports
+
+ # ----------------------------------
+ #
+ # Text-Based Replacement Recipes
+ #
+ # ----------------------------------
+
+ # Recipe to replace HttpLogDetailLevel call with HttpLogOptions.HttpLogDetailLevel
+ # Before:
+ # HttpLogDetailLevel.BODY_AND_HEADERS
+ # After:
+ # HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS
+ - org.openrewrite.text.FindAndReplace:
+ find: '(? inputTextItems = Arrays.asList(new InputTextItem(\"hello world\"));\n" +
+ " List result = textTranslationClient.translate(Arrays.asList(\"es\"), inputTextItems);\n" +
+ " }\n" +
+ "}";
+
+ @Language("java") String after = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import com.azure.ai.translation.text.models.InputTextItem;\n" +
+ "import com.azure.ai.translation.text.models.TranslatedTextItem;\n" +
+ "\n" +
+ "import java.io.IOException;\n" +
+ "import java.util.Arrays;\n" +
+ "import java.util.List;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " public void myMethod() {\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder().buildClient();\n" +
+ " List inputTextItems = Arrays.asList(new InputTextItem(\"hello world\"));\n" +
+ " List result = null;\n" +
+ " try {\n" +
+ " result = textTranslationClient.translate(Arrays.asList(\"es\"), inputTextItems);\n" +
+ " } catch (IOException e) {\n" +
+ " throw new RuntimeException(e);\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ @Test
+ void testTextTranslationClientTranslateWithResponse() {
+ @Language("java") String before = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import com.azure.ai.translation.text.models.InputTextItem;\n" +
+ "import com.azure.ai.translation.text.models.TranslatedTextItem;\n" +
+ "import com.azure.core.http.rest.RequestOptions;\n" +
+ "import com.azure.core.http.rest.Response;\n" +
+ "import com.azure.core.util.BinaryData;\n" +
+ "import com.azure.core.util.Context;\n" +
+ "import com.azure.core.util.serializer.TypeReference;\n" +
+ "\n" +
+ "import java.util.Arrays;\n" +
+ "import java.util.List;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " void myMethod() {\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder().buildClient();\n" +
+ "\n" +
+ " List inputTextItems = Arrays.asList(new InputTextItem(\"hello world\"));\n" +
+ " List targetLanguages = Arrays.asList(\"es\");\n" +
+ " BinaryData requestBody = BinaryData.fromObject(inputTextItems);\n" +
+ " RequestOptions requestOptions = new RequestOptions().setContext(Context.NONE);\n" +
+ "\n" +
+ " Response binaryDataResponse = textTranslationClient.translateWithResponse(targetLanguages, requestBody, requestOptions);\n" +
+ " List result = binaryDataResponse.getValue().toObject(new TypeReference>() { });\n" +
+ // " \n" +
+ " }\n" +
+ "}";
+
+ @Language("java") String after = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import com.azure.ai.translation.text.models.InputTextItem;\n" +
+ "import com.azure.ai.translation.text.models.TranslatedTextItem;\n" +
+ "import io.clientcore.core.http.models.RequestOptions;\n" +
+ "import io.clientcore.core.http.models.Response;\n" +
+ "import io.clientcore.core.util.Context;\n" +
+ "import io.clientcore.core.util.binarydata.BinaryData;\n" +
+ "\n" +
+ "import java.io.IOException;\n" +
+ "import java.lang.reflect.ParameterizedType;\n" +
+ "import java.lang.reflect.Type;\n" +
+ "import java.util.Arrays;\n" +
+ "import java.util.List;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " void myMethod() {\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder().buildClient();\n" +
+ "\n" +
+ " List inputTextItems = Arrays.asList(new InputTextItem(\"hello world\"));\n" +
+ " List targetLanguages = Arrays.asList(\"es\");\n" +
+ " BinaryData requestBody = BinaryData.fromObject(inputTextItems);\n" +
+ " RequestOptions requestOptions = new RequestOptions().setContext(Context.none());\n" +
+ "\n" +
+ " Response binaryDataResponse = textTranslationClient.translateWithResponse(targetLanguages, requestBody, requestOptions);\n" +
+ " List result = null;\n" +
+ " try {\n" +
+ " result = binaryDataResponse.getValue().toObject(new ParameterizedType() {\n" +
+ " @Override\n" +
+ " public Type getRawType() {\n" +
+ " return List.class;\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public Type[] getActualTypeArguments() {\n" +
+ " return new Type[]{TranslatedTextItem.class};\n" +
+ " }\n" +
+ "\n" +
+ " @Override\n" +
+ " public Type getOwnerType() {\n" +
+ " return null;\n" +
+ " } });\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ rewriteRun(
+ spec -> spec.typeValidationOptions(TypeValidation.none()),
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/AddTryCatchToMethodCallUnitTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/AddTryCatchToMethodCallUnitTest.java
new file mode 100644
index 0000000000000..111481f718e1a
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/AddTryCatchToMethodCallUnitTest.java
@@ -0,0 +1,292 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+
+import static org.openrewrite.java.Assertions.java;
+
+/**
+ * Add try-catch recipe wraps all method calls that match the supplied method pattern
+ * in a try-catch block with the provided catch code snippet.
+ * This test class tests the recipe alone.
+ */
+public class AddTryCatchToMethodCallUnitTest implements RewriteTest {
+ /**
+ * This method defines recipes used for testing.
+ * @param spec stores settings for testing environment.
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipes(new com.azure.openrewrite.AddTryCatchToMethodCallRecipe("UserClass myMethod(..)",
+ "catch (IOException e) { e.printStackTrace(); }",
+ "java.io.IOException",false),
+ new com.azure.openrewrite.AddTryCatchToMethodCallRecipe("CatchAndThrow myMethod(..)",
+ "catch (IOException e) { throw new RuntimeException(e); }",
+ "java.io.IOException",false)
+ );
+ }
+
+ @Test
+ void testAddTryCatchVoidMethod() {
+ @Language("java") String before =
+ "public class UserClass {\n" +
+ " \n" +
+ " private void myMethod() {\n" +
+ " int a = 1 + 1;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = 2 + 2;\n" +
+ " myMethod();\n" +
+ " int c = 3;\n" +
+ " }\n" +
+ "}\n";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " \n" +
+ " private void myMethod() {\n" +
+ " int a = 1 + 1;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = 2 + 2;\n" +
+ " try {\n" +
+ " myMethod();\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " int c = 3;\n" +
+ " }\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ @Test
+ void testAddTryCatchMethodInVarDeclaration() {
+ @Language("java") String before =
+ "public class UserClass {\n" +
+ " \n" +
+ " private int myMethod() {\n" +
+ " return 2;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = myMethod();\n" +
+ " }\n" +
+ "}\n";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " \n" +
+ " private int myMethod() {\n" +
+ " return 2;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = null;\n" +
+ " try {\n" +
+ " b = myMethod();\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ @Test
+ void testAddTryCatchMethodInAssignment() {
+ @Language("java") String before =
+ "public class UserClass {\n" +
+ " \n" +
+ " private int myMethod() {\n" +
+ " return 2;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b;\n" +
+ " b = myMethod();\n" +
+ " int a = b;\n" +
+ " }\n" +
+ "}\n";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " \n" +
+ " private int myMethod() {\n" +
+ " return 2;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b;\n" +
+ " try {\n" +
+ " b = myMethod();\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " int a = b;\n" +
+ " }\n"+
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ @Test
+ void testAddTryCatchMethodIsFromInstance() {
+ @Language("java") String before =
+ "public class UserClass {\n" +
+ " public UserClass(){}\n" +
+ " String s = \"Hello\";\n" +
+ " \n" +
+ " public String myMethod(int a, String b) {\n" +
+ " return s;\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class UserClass2 {" +
+ " \n" +
+ " public void myMethod2() {\n" +
+ " UserClass c = new UserClass();\n" +
+ " String s2 = c.myMethod(3, \"hello\");\n" +
+ " }\n" +
+ "}\n";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " public UserClass(){}\n" +
+ " String s = \"Hello\";\n" +
+ " \n" +
+ " public String myMethod(int a, String b) {\n" +
+ " return s;\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class UserClass2 {" +
+ " \n" +
+ " public void myMethod2() {\n" +
+ " UserClass c = new UserClass();\n" +
+ " String s2 = null;\n" +
+ " try {\n" +
+ " s2 = c.myMethod(3, \"hello\");\n" +
+ " } catch (IOException e) {\n" +
+ " e.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ @Test
+ void testAddTryCatchMethodIsInNestedCall() {
+ @Language("java") String before =
+ "public class CatchAndThrow {\n" +
+ " public CatchAndThrow(){}\n" +
+ " String s = \"Hello\";\n" +
+ " \n" +
+ " public String myMethod() {\n" +
+ " return s;\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class UserClass2 {\n" +
+ " CatchAndThrow c = new CatchAndThrow();\n" +
+ "}\n" +
+ "class UserClass3 {\n" +
+ " UserClass2 c2 = new UserClass2();\n" +
+ " public void myMethod3() {\n" +
+ " String s = c2.c.myMethod();\n" +
+ " }\n" +
+ "}";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class CatchAndThrow {\n" +
+ " public CatchAndThrow(){}\n" +
+ " String s = \"Hello\";\n" +
+ " \n" +
+ " public String myMethod() {\n" +
+ " return s;\n" +
+ " }\n" +
+ "}\n" +
+ "\n" +
+ "class UserClass2 {\n" +
+ " CatchAndThrow c = new CatchAndThrow();\n" +
+ "}\n" +
+ "class UserClass3 {\n" +
+ " UserClass2 c2 = new UserClass2();\n" +
+ " public void myMethod3() {\n" +
+ " String s = null;\n" +
+ " try {\n" +
+ " s = c2.c.myMethod();\n" +
+ " } catch (IOException e) {\n" +
+ " throw new RuntimeException(e);\n" +
+ //" e.printStackTrace();\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+ @Test
+ void testAddTryCatchThrows() {
+ @Language("java") String before =
+ "public class CatchAndThrow {\n" +
+ " \n" +
+ " private void myMethod() {\n" +
+ " int a = 1 + 1;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = 2 + 2;\n" +
+ " myMethod();\n" +
+ " int c = 3;\n" +
+ " }\n" +
+ "}\n";
+
+ @Language("java") String after = "import java.io.IOException;\n" +
+ "\n" +
+ "public class CatchAndThrow {\n" +
+ " \n" +
+ " private void myMethod() {\n" +
+ " int a = 1 + 1;\n" +
+ " }\n" +
+ " \n" +
+ " private void anotherMethod(){\n" +
+ " int b = 2 + 2;\n" +
+ " try {\n" +
+ " myMethod();\n" +
+ " } catch (IOException e) {\n" +
+ " throw new RuntimeException(e);\n" +
+ " }\n" +
+ " int c = 3;\n" +
+ " }\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/BinaryDataTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/BinaryDataTest.java
new file mode 100644
index 0000000000000..9294139486274
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/BinaryDataTest.java
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+import org.openrewrite.test.TypeValidation;
+
+public class BinaryDataTest implements RewriteTest {
+ /**
+ * BinaryDataTest tests the recipe that changes
+ * com.azure.core.util.BinaryData to io.clientcore.core.util.binarydata.BinaryData.
+ * This recipe also tests to ensure that the TypeReference is correctly changed
+ * when used in conjunction with BinaryData.
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ // Added due to bug in OpenRewrite parser when parsing azure TypeReference instantiation
+ spec.typeValidationOptions(TypeValidation.none());
+ }
+
+ /* Test to make sure BinaryData import is changed */
+ @Test
+ public void testBinaryDataImportChanged() {
+ @Language("java") String before = "import com.azure.core.util.BinaryData;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n BinaryData b = BinaryData.fromObject(null);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.util.binarydata.BinaryData;";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n BinaryData b = BinaryData.fromObject(null);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /* Test to make sure BinaryData type is changed */
+ @Test
+ public void testBinaryDataTypeChanged() {
+ @Language("java") String before = "";
+ before += "public class Testing {\n public Testing(){\n com.azure.core.util.BinaryData b = com.azure.core.util.BinaryData.fromObject(null);\n }\n}";
+
+ @Language("java") String after = "";
+ after += "public class Testing {\n public Testing(){\n io.clientcore.core.util.binarydata.BinaryData b = io.clientcore.core.util.binarydata.BinaryData.fromObject(null);\n }\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /* Test to make sure BinaryData type and import is changed and TypeReference is changed */
+ @Test
+ @Disabled("This test is failing and is temporarily disabled")
+ void testBinaryDataTypeReferenceChange() {
+ @Language("java") String before = "";
+ before += "\nimport java.lang.reflect.ParameterizedType;";
+ before += "\nimport java.lang.reflect.Type;";
+ before += "\nimport java.util.List;";
+ before += "\nimport com.azure.core.util.serializer.TypeReference;";
+ before += "\nimport com.azure.core.util.BinaryData;";
+ before += "\npublic class Testing {";
+ before += "\n private static final TypeReference> TESTING_TYPE = new TypeReference>() {\n };";
+ before += "\n private static final BinaryData b = BinaryData.fromObject(null);";
+ before += "\n public static void main(String[] args) {";
+ before += "\n System.out.println(b.toObject(TESTING_TYPE));";
+ before += "\n }";
+ before += "\n}";
+
+
+ @Language("java") String after =
+ "import io.clientcore.core.util.binarydata.BinaryData;\n\n" +
+ "import java.io.IOException;\n" +
+ "import java.lang.reflect.ParameterizedType;\n" +
+ "import java.lang.reflect.Type;\n" +
+ "import java.util.List;\n\n"+
+ "public class Testing {\n" +
+ " private static final Type TESTING_TYPE = new ParameterizedType() {\n" +
+ " @Override\n" +
+ " public Type getRawType() {\n" +
+ " return List.class;\n" +
+ " }\n\n" +
+ " @Override\n" +
+ " public Type[] getActualTypeArguments() {\n" +
+ " return new Type[]{String.class};\n" +
+ " }\n\n" +
+ " @Override\n" +
+ " public Type getOwnerType() {\n" +
+ " return null;\n" +
+ " }\n";
+ after += " };";
+ after += "\n private static final BinaryData b = BinaryData.fromObject(null);";
+ after += "\n public static void main(String[] args) {";
+ after += "\n try {";
+ after += "\n System.out.println(b.toObject(TESTING_TYPE));";
+ after += "\n } catch (IOException e) {";
+ after += "\n e.printStackTrace();";
+ after += "\n }";
+ after += "\n }\n";
+ after += "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ClientLoggerTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ClientLoggerTest.java
new file mode 100644
index 0000000000000..e21a5086d4ef0
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ClientLoggerTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+public class ClientLoggerTest implements RewriteTest {
+ /**
+ * ClientLoggerTest tests the recipe that changes
+ * com.azure.core.util.logging.ClientLogger to io.clientcore.core.util.ClientLogger.
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /* Test to make sure ClientLogger import is changed */
+ @Test
+ public void testClientLoggerWithImport() {
+ @Language("java") String before = "import com.azure.core.util.logging.ClientLogger;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n ClientLogger c = new ClientLogger(Testing.class);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.util.ClientLogger;";
+ after += "\n\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n ClientLogger c = new ClientLogger(Testing.class);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+
+ /* Test to make sure ClientLogger type is changed */
+ @Test
+ public void testClientLoggerWithFullyQualifiedName() {
+ @Language("java") String before = "public class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.util.logging.ClientLogger c = new com.azure.core.util.logging.ClientLogger(Testing.class);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "public class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.util.ClientLogger c = new io.clientcore.core.util.ClientLogger(Testing.class);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ContextTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ContextTest.java
new file mode 100644
index 0000000000000..bbb4eef762851
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ContextTest.java
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * ContextTest is used to test out the recipe that converts code to use the
+ * new clientcore Context class.
+ */
+public class ContextTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * This test method is used to make sure that the Context class is updated
+ */
+ @Test
+ void testImportReplaceContext() {
+ @Language("java") String before = "import com.azure.core.util.Context;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){}";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.util.Context;";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){}";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CoreUtilsTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CoreUtilsTest.java
new file mode 100644
index 0000000000000..b2f674fafaa0e
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CoreUtilsTest.java
@@ -0,0 +1,66 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+public class CoreUtilsTest implements RewriteTest {
+ /**
+ * Test migrations from
+ * com.azure.core.util.CoreUtils to com.azure.core.v2.util.CoreUtils
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /* Tests that CoreUtil import is changed */
+ @Test
+ public void testConfigurationImportChanged() {
+ @Language("java") String before = "import com.azure.core.util.CoreUtils;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n CoreUtils cu = new CoreUtils();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import com.azure.core.v2.util.CoreUtils;";
+ after += "\n\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n CoreUtils cu = new CoreUtils();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /* Tests that CoreUtils type is changed */
+ @Test
+ public void testConfigurationTypeChanged() {
+ @Language("java") String before = "";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.util.CoreUtils cu = new com.azure.core.util.CoreUtils();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "";
+ after += "public class Testing {";
+ after += "\n public Testing(){";
+ after += "\n com.azure.core.v2.util.CoreUtils cu = new com.azure.core.v2.util.CoreUtils();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+}
+
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CredentialTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CredentialTest.java
new file mode 100644
index 0000000000000..e38951b687348
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/CredentialTest.java
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * CredentialTest is used to test out the recipe that changes the package name com.azure.core.credential
+ * to io.clientcore.core.credential.
+ */
+public class CredentialTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * This test method is used to make sure that the package com.azure.core.credential is changed
+ */
+ @Test
+ void testCredentialPackageNameChange() {
+ @Language("java") String before = "import com.azure.core.credential.KeyCredential;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n KeyCredential kc = new KeyCredential(\"\");";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.credential.KeyCredential;";
+ after += "\n\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n KeyCredential kc = new KeyCredential(\"\");";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /**
+ * This test method is used to make sure that the KeyCredential type is changed
+ */
+ @Test
+ void testKeyCredentialChangeNoImport() {
+ @Language("java") String before = "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.credential.KeyCredential kc = new com.azure.core.credential.KeyCredential(\"\");";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.credential.KeyCredential kc = new io.clientcore.core.credential.KeyCredential(\"\");";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /**
+ * This test method is used to make sure that KeyCredentialPolicy type and import is changed
+ */
+ @Test
+ void testKeyCredentialPolicyTypeAndImportChange() {
+ @Language("java") String before = "import com.azure.core.http.policy.KeyCredentialPolicy;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.http.policy.KeyCredentialPolicy kc = new KeyCredentialPolicy(\"key\", null);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.pipeline.KeyCredentialPolicy;";
+ after += "\n\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.http.pipeline.KeyCredentialPolicy kc = new KeyCredentialPolicy(\"key\", null);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /**
+ * This test method is used to make sure that KeyCredentialTrait type and import is changed
+ */
+ @Test
+ void testKeyCredentialTraitTypeAndImportChange() {
+ @Language("java") String before = "import com.azure.core.client.traits.KeyCredentialTrait;";
+ before += "\npublic class Testing implements KeyCredentialTrait{";
+ before += "\n public Testing(){";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.models.traits.KeyCredentialTrait;";
+ after += "\n\npublic class Testing implements KeyCredentialTrait {";
+ after += "\n public Testing(){";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ExceptionTypesTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ExceptionTypesTest.java
new file mode 100644
index 0000000000000..c84682dd7c9bd
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ExceptionTypesTest.java
@@ -0,0 +1,206 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+public class ExceptionTypesTest implements RewriteTest {
+ /**
+ * ExceptionTypesTest tests exception migrations from azure-core v1
+ * to azure-core-v2 and client-core.
+ * Recipes used: ChangeType
+ * From:
+ * com.azure.core.exception
+ * ClientAuthenticationException
+ * HttpResponseException
+ * ResourceModifiedException
+ * ResourceNotFoundException
+ * To:
+ * com.azure.core.v2.exception
+ * ClientAuthenticationException
+ * ResourceModifiedException
+ * ResourceNotFoundException
+ * io.clientcore.core.http.exception
+ * HttpResponseException
+ *
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /* Testing ChangeType recipes */
+ @Test
+ public void testClientAuthenticationExceptionChanged() {
+ @Language("java") String before = "import com.azure.core.exception.ClientAuthenticationException;";
+ before += "\npublic class Testing {";
+ before += "\n public void testMethod() {";
+ before += "\n try {";
+ before += "\n // Some code that may throw ClientAuthenticationException";
+ before += "\n } catch (ClientAuthenticationException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import com.azure.core.v2.exception.ClientAuthenticationException;";
+ after += "\n\npublic class Testing {";
+ after += "\n public void testMethod() {";
+ after += "\n try {";
+ after += "\n // Some code that may throw ClientAuthenticationException";
+ after += "\n } catch (ClientAuthenticationException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n }";
+ after += "\n}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+
+ @Test
+ public void testHttpResponseExceptionChanged() {
+ @Language("java") String before = "import com.azure.core.exception.HttpResponseException;";
+ before += "\npublic class Testing {";
+ before += "\n public void testMethod() {";
+ before += "\n try {";
+ before += "\n // Some code that may throw HttpResponseException";
+ before += "\n } catch (HttpResponseException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.exception.HttpResponseException;";
+ after += "\n\npublic class Testing {";
+ after += "\n public void testMethod() {";
+ after += "\n try {";
+ after += "\n // Some code that may throw HttpResponseException";
+ after += "\n } catch (HttpResponseException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n }";
+ after += "\n}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+
+ @Test
+ public void testResourceModifiedExceptionChanged() {
+ @Language("java") String before = "import com.azure.core.exception.ResourceModifiedException;";
+ before += "\npublic class Testing {";
+ before += "\n public void testMethod() {";
+ before += "\n try {";
+ before += "\n // Some code that may throw ResourceModifiedException";
+ before += "\n } catch (ResourceModifiedException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import com.azure.core.v2.exception.ResourceModifiedException;";
+ after += "\n\npublic class Testing {";
+ after += "\n public void testMethod() {";
+ after += "\n try {";
+ after += "\n // Some code that may throw ResourceModifiedException";
+ after += "\n } catch (ResourceModifiedException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n }";
+ after += "\n}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+
+ @Test
+ public void testResourceNotFoundExceptionChanged() {
+ @Language("java") String before = "import com.azure.core.exception.ResourceNotFoundException;";
+ before += "\npublic class Testing {";
+ before += "\n public void testMethod() {";
+ before += "\n try {";
+ before += "\n // Some code that may throw ResourceNotFoundException";
+ before += "\n } catch (ResourceNotFoundException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import com.azure.core.v2.exception.ResourceNotFoundException;";
+ after += "\n\npublic class Testing {";
+ after += "\n public void testMethod() {";
+ after += "\n try {";
+ after += "\n // Some code that may throw ResourceNotFoundException";
+ after += "\n } catch (ResourceNotFoundException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n }";
+ after += "\n}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /**
+ * Will fail and need updating if all azure-core v1 exceptions are migrated,
+ * or if all exceptions are migrated to the same directory.
+ */
+ @Test
+ public void testBundledImportsChanged() {
+ @Language("java") String before = "import com.azure.core.exception.*;";
+ before += "\npublic class Testing {";
+ before += "\n public void testMethod() {";
+ before += "\n try {";
+ before += "\n // Some code that may throw ClientAuthenticationException";
+ before += "\n throw new ClientAuthenticationException(null,null);";
+ before += "\n } catch (ClientAuthenticationException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n try {";
+ before += "\n // Some code that may throw HttpResponseException";
+ before += "\n throw new HttpResponseException(null,null);";
+ before += "\n } catch (HttpResponseException e) {";
+ before += "\n // Handle exception";
+ before += "\n }";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import com.azure.core.exception.*;" +
+ "\nimport com.azure.core.v2.exception.ClientAuthenticationException;" +
+ "\nimport io.clientcore.core.http.exception.HttpResponseException;";
+ after += "\n\npublic class Testing {";
+ after += "\n public void testMethod() {";
+ after += "\n try {";
+ after += "\n // Some code that may throw ClientAuthenticationException";
+ after += "\n throw new ClientAuthenticationException(null,null);";
+ after += "\n } catch (ClientAuthenticationException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n try {";
+ after += "\n // Some code that may throw HttpResponseException";
+ after += "\n throw new HttpResponseException(null,null);";
+ after += "\n } catch (HttpResponseException e) {";
+ after += "\n // Handle exception";
+ after += "\n }";
+ after += "\n }";
+ after += "\n}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpHeaderNameTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpHeaderNameTest.java
new file mode 100644
index 0000000000000..9c45314e09882
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpHeaderNameTest.java
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+public class HttpHeaderNameTest implements RewriteTest {
+ /**
+ * HttpHeaderNameTest tests the recipe that changes
+ * com.azure.core.http.HttpHeaderName to io.clientcore.core.http.models.HttpHeaderName.
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /* Test to make sure HttpHeaderName type is changed */
+ @Test
+ public void testHeaderNameTypeChanged() {
+ @Language("java") String before = "";
+ before += "public class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.http.HttpHeaderName h = new com.azure.core.http.HttpHeaderName();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "";
+ after += "public class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.http.models.HttpHeaderName h = new io.clientcore.core.http.models.HttpHeaderName();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /* Test to make sure HttpHeaderName import is changed */
+ @Test
+ public void testHeaderNameImportChanged() {
+ @Language("java") String before = "import com.azure.core.http.HttpHeaderName;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n HttpHeaderName h = new HttpHeaderName();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.HttpHeaderName;";
+ after += "\n\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n HttpHeaderName h = new HttpHeaderName();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpLogOptionsTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpLogOptionsTest.java
new file mode 100644
index 0000000000000..80030f24622bc
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/HttpLogOptionsTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+public class HttpLogOptionsTest implements RewriteTest {
+ /**
+ * HttpLogOptionsTest tests the recipe that changes
+ * com.azure.core.http.policy.HttpLogDetailLevel to io.clientcore.core.http.models.HttpLogOptions.HttpLogDetailLevel
+ * and com.azure.core.http.policy.HttpLogOptions to io.clientcore.core.http.models.HttpLogOptions
+ *
+ */
+
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /* Test to make sure HttpLogOptions and HttpLogDetailLevel imports are changed*/
+ @Test
+ public void testHttpLogOptionsLogLevelImportsChanged() {
+ @Language("java") String before = "import com.azure.core.http.policy.HttpLogOptions;";
+ before += "\nimport com.azure.core.http.policy.HttpLogDetailLevel;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n HttpLogOptions h = new HttpLogOptions();h.setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.HttpLogOptions;";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n HttpLogOptions h = new HttpLogOptions();h.setLogLevel(HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+
+
+ /* Test to make sure HttpLogOptions and HttpLogDetailLevel type is changed*/
+ @Test
+ public void testHttpLogOptionsLogLevelTypesChanged() {
+ @Language("java") String before = "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.http.policy.HttpLogOptions h = new com.azure.core.http.policy.HttpLogOptions();h.setLogLevel(com.azure.core.http.policy.HttpLogDetailLevel.BODY_AND_HEADERS);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.http.models.HttpLogOptions h = new io.clientcore.core.http.models.HttpLogOptions();h.setLogLevel( io.clientcore.core.http.models.HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS);";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RequestOptionsTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RequestOptionsTest.java
new file mode 100644
index 0000000000000..f4bbbb4a33dee
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RequestOptionsTest.java
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * RequestOptionsTest is used to test out the recipe that converts com.azure.core.http.rest.RequestOptions
+ * to io.clientcore.core.http.models.RequestOptions.
+ */
+public class RequestOptionsTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * This test method is used to make sure that the class import for RequestOptions is updated
+ */
+ @Test
+ void testChangeRequestImportWithImport() {
+ @Language("java") String before = "import com.azure.core.http.rest.RequestOptions;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n RequestOptions r = new RequestOptions();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.RequestOptions;";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n RequestOptions r = new RequestOptions();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+
+ /**
+ * This test method is used to make sure that the class type for RequestOptions is updated
+ */
+ @Test
+ void testChangeRequestImportWithFullyQualifiedName() {
+ @Language("java") String before = "public class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.http.rest.RequestOptions r = new com.azure.core.http.rest.RequestOptions();";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "public class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.http.models.RequestOptions r = new io.clientcore.core.http.models.RequestOptions();";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ResponseTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ResponseTest.java
new file mode 100644
index 0000000000000..c5eaa3f6cdd1c
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/ResponseTest.java
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * ResponseTest is used to test out the recipe that changes
+ * references to com.azure.core.http.rest.response to
+ * io.clientcore.core.http.models.response.
+ */
+public class ResponseTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * This test method is used to make sure that the Response import is updated to the new version
+ */
+ @Test
+ void testUpdateResponseTypeWithImport() {
+ @Language("java") String before = "import com.azure.core.http.rest.Response;\n";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n Response str = null;";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.Response;\n";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n Response str = null;";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+ /**
+ * This test method is used to make sure that the Response type is updated to the new version
+ */
+ @Test
+ void testUpdateResponseTypeWithFullyQualifiedName() {
+ @Language("java") String before = "public class Testing {";
+ before += "\n public Testing(){";
+ before += "\n com.azure.core.http.rest.Response str = null;";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "public class Testing {";
+ after += "\n public Testing(){";
+ after += "\n io.clientcore.core.http.models.Response str = null;";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before, after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RetryOptionsConstructorTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RetryOptionsConstructorTest.java
new file mode 100644
index 0000000000000..dece38898a387
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/RetryOptionsConstructorTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * RetryOptionsTest is used to test out the recipe that removes usage of
+ * FixedDelay and ExponentialDelay from the RetryOptions constructor and updates
+ * it to use the new azure-core-v2 HttpRetryOptions class.
+ */
+public class RetryOptionsConstructorTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * This test method is used to make sure that RetryOptions is updated to the new constructor and class
+ */
+ @Test
+ void testChangeRetryOptionsType() {
+ @Language("java") String before = "import com.azure.core.http.policy.RetryOptions;import java.time.Duration;import com.azure.core.http.policy.FixedDelayOptions;";
+ before += "\npublic class Testing {";
+ before += "\n public Testing(){";
+ before += "\n RetryOptions r = new RetryOptions(new FixedDelayOptions(3, Duration.ofMillis(50)));";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.HttpRetryOptions;\n\nimport java.time.Duration;\n";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n HttpRetryOptions r = new HttpRetryOptions(3, Duration.ofMillis(50));";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+ /**
+ * This test method is used to make sure that RetryOptions is updated to the new constructor and class
+ * if the FixedDelayOptions is passed as a variable and not a direct instantiation in the constructor of
+ * the RetryOptions.
+ */
+ @Test
+ void testChangeRetryOptionsTypeNoArgInit() {
+ @Language("java") String before = "import com.azure.core.http.policy.RetryOptions;import java.time.Duration;import com.azure.core.http.policy.FixedDelayOptions;";
+ before += "\npublic class Testing {";
+ before += "\n FixedDelayOptions f = new FixedDelayOptions(3, Duration.ofMillis(50));";
+ before += "\n public Testing(){";
+ before += "\n RetryOptions r = new RetryOptions(f);";
+ before += "\n }";
+ before += "\n}";
+
+ @Language("java") String after = "import io.clientcore.core.http.models.HttpRetryOptions;\n\nimport java.time.Duration;\n";
+ after += "\npublic class Testing {";
+ after += "\n public Testing(){";
+ after += "\n HttpRetryOptions r = new HttpRetryOptions(3, Duration.ofMillis(50));";
+ after += "\n }";
+ after += "\n}";
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TextTranslationClientBuilderHttpTraitTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TextTranslationClientBuilderHttpTraitTest.java
new file mode 100644
index 0000000000000..dddb0582339d3
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TextTranslationClientBuilderHttpTraitTest.java
@@ -0,0 +1,181 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * HttpTraitTest tests interface migration from com.azure.core.client.traits.HttpTrait
+ * to io.clientcore.core.models.traits.HttpTrait.
+ * Tests simple method renaming with declarative recipe.
+ */
+
+public class TextTranslationClientBuilderHttpTraitTest implements RewriteTest {
+ /**
+ * This method defines recipes used for testing.
+ * @param spec stores settings for testing environment.
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ }
+
+ /**
+ * Test simple declarative rename of:
+ * retryOptions to httpRetryOptions
+ * pipeline to httpPipeline
+ * addPolicy to addHttpPipelinePolicy
+ * and complex rename of clientOptions to httpRedirectOptions
+ */
+ @Test
+ void testMethodsRenamedSuccessful() {
+ @Language("java") String before = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ "\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .pipeline(null)\n" +
+ " .addPolicy(null)\n" +
+ " .retryOptions(null)\n" +
+ " .buildClient();\n" +
+ "\n" +
+ "}\n";
+
+
+ @Language("java") String after = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ "\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .httpPipeline(null)\n" +
+ " .addHttpPipelinePolicy(null)\n" +
+ " .httpRetryOptions(null)\n" +
+ " .buildClient();\n" +
+ "\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+
+ @Test
+ void testUninitializedParamsAndImportsChanged() {
+ @Language("java") String before = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import com.azure.core.http.HttpClient;\n" +
+ "import com.azure.core.http.HttpPipeline;\n" +
+ "import com.azure.core.http.policy.HttpLogOptions;\n" +
+ "import com.azure.core.http.policy.HttpPipelinePolicy;\n" +
+ "import com.azure.core.http.policy.RetryOptions;\n" +
+ //"import com.azure.core.util.ClientOptions;" +
+ "\n" +
+ "public class UserClass{\n" +
+ " \n" +
+ " HttpClient client;\n" +
+ " HttpPipeline pipeline;\n" +
+ " HttpPipelinePolicy httpPipelinePolicy;\n" +
+ " RetryOptions retryOptions;\n" +
+ " HttpLogOptions logOptions;\n" +
+ //" ClientOptions clientOptions;\n" +
+ " \n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .httpClient(client)\n" +
+ " .pipeline(pipeline)\n" +
+ " .addPolicy(httpPipelinePolicy)\n" +
+ " .retryOptions(retryOptions)\n" +
+ " .httpLogOptions(logOptions)\n" +
+ //" .clientOptions(clientOptions)\n" +
+ " .buildClient();\n" +
+ "}";
+
+
+ @Language("java") String after = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import io.clientcore.core.http.client.HttpClient;\n" +
+ "import io.clientcore.core.http.models.HttpLogOptions;\n" +
+ "import io.clientcore.core.http.models.HttpRetryOptions;\n" +
+ "import io.clientcore.core.http.pipeline.HttpPipeline;\n" +
+ "import io.clientcore.core.http.pipeline.HttpPipelinePolicy;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ " \n" +
+ " HttpClient client;\n" +
+ " HttpPipeline pipeline;\n" +
+ " HttpPipelinePolicy httpPipelinePolicy;\n" +
+ " HttpRetryOptions retryOptions;\n" +
+ " HttpLogOptions logOptions;\n" +
+ " \n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .httpClient(client)\n" +
+ " .httpPipeline(pipeline)\n" +
+ " .addHttpPipelinePolicy(httpPipelinePolicy)\n" +
+ " .httpRetryOptions(retryOptions)\n" +
+ " .httpLogOptions(logOptions)\n" +
+ " .buildClient();\n" +
+ "}";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+
+
+ @Test
+ void testLikeSampleImplementationChanged() {
+ @Language("java") String before = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import com.azure.core.credential.AzureKeyCredential;\n" +
+ "import com.azure.core.http.policy.FixedDelayOptions;\n" +
+ "import com.azure.core.http.policy.HttpLogDetailLevel;\n" +
+ "import com.azure.core.http.policy.HttpLogOptions;\n" +
+ "import com.azure.core.http.policy.RetryOptions;\n" +
+ "import java.time.Duration;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ "\n" +
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .credential(new AzureKeyCredential(\"\"))\n" +
+ " .endpoint(\"\")\n" +
+ " .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS))\n" +
+ " .retryOptions(new RetryOptions(new FixedDelayOptions(3, Duration.ofMillis(50))))\n" +
+ " .buildClient();" +
+ "\n" +
+ "}\n";
+
+
+ @Language("java") String after = "import com.azure.ai.translation.text.TextTranslationClient;\n" +
+ "import com.azure.ai.translation.text.TextTranslationClientBuilder;\n" +
+ "import io.clientcore.core.credential.AzureKeyCredential;\n" +
+ "import io.clientcore.core.http.models.HttpLogOptions;\n" +
+ "import io.clientcore.core.http.models.HttpRetryOptions;\n\n" +
+ "import java.time.Duration;\n" +
+ "\n" +
+ "public class UserClass {\n" +
+ "\n" +
+
+ " TextTranslationClient textTranslationClient = new TextTranslationClientBuilder()\n" +
+ " .credential(new AzureKeyCredential(\"\"))\n" +
+ " .endpoint(\"\")\n" +
+ // Copied from azure-ai-translation-text-v2 TextTranslationSample
+ // Not affected at all
+ " .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogOptions.HttpLogDetailLevel.BODY_AND_HEADERS))\n" +
+ " .httpRetryOptions(new HttpRetryOptions(3, Duration.ofMillis(50)))\n" +
+ " .buildClient();" +
+ "\n" +
+ "}\n";
+
+ rewriteRun(
+ java(before,after)
+ );
+ }
+}
diff --git a/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TypeReferenceTest.java b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TypeReferenceTest.java
new file mode 100644
index 0000000000000..4f19caa4bcabb
--- /dev/null
+++ b/sdk/tools/azure-openrewrite/src/test/java/com/azure/openrewrite/recipe/TypeReferenceTest.java
@@ -0,0 +1,150 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.openrewrite.recipe;
+
+
+import org.intellij.lang.annotations.Language;
+import org.junit.jupiter.api.Test;
+import static org.openrewrite.java.Assertions.java;
+import org.openrewrite.test.RecipeSpec;
+import org.openrewrite.test.RewriteTest;
+import org.openrewrite.test.TypeValidation;
+
+/**
+ * TypeReferenceTest is used to test out the recipe that changes the usage of TypeReference (azure core v1)
+ * to ParameterizedType (azure core v2)
+ */
+public class TypeReferenceTest implements RewriteTest {
+
+ /**
+ * This method sets which recipe should be used for testing
+ * @param spec stores settings for testing environment; e.g. which recipes to use for testing
+ */
+ @Override
+ public void defaults(RecipeSpec spec) {
+ spec.recipeFromResource("/META-INF/rewrite/rewrite.yml",
+ "com.azure.openrewrite.migrateToVNext");
+ // Added due to bug in OpenRewrite parser when parsing azure TypeReference instantiation
+ spec.typeValidationOptions(TypeValidation.none());
+ }
+
+ /**
+ * This test method is used to make sure that TypeReference is correctly
+ * changed to ParameterizedType when using List generic type
+ */
+ @Test
+ void testTypeReferenceVariableDeclarationChangeList() {
+ @Language("java") String before = "";
+ before += "\nimport java.lang.reflect.ParameterizedType;";
+ before += "\nimport java.lang.reflect.Type;";
+ before += "\nimport java.util.List;";
+ before += "\nimport com.azure.core.util.serializer.TypeReference;";
+ before += "\npublic class Testing {";
+ before += "\n private static final TypeReference> TESTING_TYPE = new TypeReference>() {\n };";
+ before += "\n}";
+
+
+ @Language("java") String after = "import java.lang.reflect.ParameterizedType;\n" +
+ "import java.lang.reflect.Type;\n" +
+ "import java.util.List;\n\n"+
+ "public class Testing {\n" +
+ " private static final Type TESTING_TYPE = new ParameterizedType() {\n" +
+ " @Override\n" +
+ " public Type getRawType() {\n" +
+ " return List.class;\n" +
+ " }\n\n" +
+ " @Override\n" +
+ " public Type[] getActualTypeArguments() {\n" +
+ " return new Type[]{String.class};\n" +
+ " }\n\n" +
+ " @Override\n" +
+ " public Type getOwnerType() {\n" +
+ " return null;\n" +
+ " }\n" +
+ " };\n" +
+ "}\n";
+
+ rewriteRun(
+
+ java(before,after)
+ );
+ }
+ /**
+ * This test method is used to make sure that TypeReference is correctly
+ * changed to ParameterizedType when using Map generic type
+ */
+ @Test
+ void testTypeReferenceVariableDeclarationChangeMap() {
+ @Language("java") String before = "";
+ before += "\nimport java.lang.reflect.ParameterizedType;";
+ before += "\nimport java.lang.reflect.Type;";
+ before += "\nimport java.util.Map;";
+ before += "\nimport com.azure.core.util.serializer.TypeReference;";
+ before += "\npublic class Testing {";
+ before += "\n private static final TypeReference