From df8cd5945d769dec632080cdb6a9b4ac5f459ce2 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Tue, 31 Mar 2026 18:56:12 +0000 Subject: [PATCH 1/2] Use `JavaTemplate.apply()` static method Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.recipes.UseJavaTemplateStaticApply?organizationId=QUxML01vZGVybmUvTW9kZXJuZSArIE9wZW5SZXdyaXRl Co-authored-by: Moderne --- .../MigrateDependenciesToVersionCatalog.java | 16 +------ .../gradle/GradleJavaTemplateTest.java | 4 +- .../java/JavaTemplateContextFreeTest.java | 20 ++------ .../java/JavaTemplateInstanceOfTest.java | 8 +--- .../java/JavaTemplateNamedTest.java | 13 ++---- .../java/JavaTemplateSubstitutionsTest.java | 16 ++----- .../openrewrite/java/JavaTemplateTest.java | 46 ++++--------------- .../java/JavaTemplateTest3Test.java | 4 +- .../java/JavaTemplateTest4Test.java | 4 +- .../java/JavaTemplateTest6Test.java | 4 +- .../java/JavaTemplateTest7Test.java | 19 +++----- .../org/openrewrite/java/JavaTemplate.java | 2 +- 12 files changed, 38 insertions(+), 118 deletions(-) diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/MigrateDependenciesToVersionCatalog.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/MigrateDependenciesToVersionCatalog.java index 06bd10bcb74..534a7a2de12 100644 --- a/rewrite-gradle/src/main/java/org/openrewrite/gradle/MigrateDependenciesToVersionCatalog.java +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/MigrateDependenciesToVersionCatalog.java @@ -491,13 +491,7 @@ private Expression transformDependencyToVersionCatalog(Expression arg, J.MethodI if (dep != null) { boolean hasMultipleArgs = methodInvocation.getArguments().size() > 1; - Expression catalogRef = JavaTemplate.builder("libs.#{}") - .build() - .apply( - new Cursor(getCursor(), arg), - arg.getCoordinates().replace(), - dep.getAliasName() - ); + Expression catalogRef = JavaTemplate.apply("libs.#{}", new Cursor(getCursor(), arg), arg.getCoordinates().replace(), dep.getAliasName()); catalogRef = catalogRef.withPrefix(literal.getPrefix()); @@ -526,13 +520,7 @@ private Expression transformDependencyToVersionCatalog(Expression arg, J.MethodI if (dep.gav.getGroupId().equals(group) && dep.gav.getArtifactId().equals(artifact)) { boolean hasMultipleArgs = methodInvocation.getArguments().size() > 1; - Expression catalogRef = JavaTemplate.builder("libs.#{}") - .build() - .apply( - new Cursor(getCursor(), arg), - arg.getCoordinates().replace(), - dep.getAliasName() - ); + Expression catalogRef = JavaTemplate.apply("libs.#{}", new Cursor(getCursor(), arg), arg.getCoordinates().replace(), dep.getAliasName()); catalogRef = catalogRef.withPrefix(gstring.getPrefix()); diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/GradleJavaTemplateTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/GradleJavaTemplateTest.java index a6a1d376314..dcbd13ec1d7 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/GradleJavaTemplateTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/GradleJavaTemplateTest.java @@ -34,9 +34,7 @@ void useJavaTemplateInBuildGradle() { @Override public J.Block visitBlock(J.Block block, ExecutionContext ctx) { if (block.getStatements().isEmpty()) { - return JavaTemplate.builder("implementation(\"com.google.guava:guava:latest.release\")") - .build() - .apply(getCursor(), block.getCoordinates().lastStatement()); + return JavaTemplate.apply("implementation(\"com.google.guava:guava:latest.release\")", getCursor(), block.getCoordinates().lastStatement()); } return super.visitBlock(block, ctx); } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateContextFreeTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateContextFreeTest.java index b36135dabdf..3118c5fb500 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateContextFreeTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateContextFreeTest.java @@ -167,9 +167,7 @@ void contextFreeTypeParameter() { @Override public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { if ("o".equals(multiVariable.getVariables().getFirst().getSimpleName())) { - return JavaTemplate.builder("var o = #{any()};") - .build() - .apply(getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); + return JavaTemplate.apply("var o = #{any()};", getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); } return multiVariable; } @@ -241,9 +239,7 @@ void contextFreeTypeParameterConflictNames_broken() { @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) { if ("printf".equals(method.getSimpleName()) && method.getArguments().size() == 2) { - return JavaTemplate.builder("System.out.printf(#{any()}, #{any()}, 0);") - .build() - .apply(getCursor(), method.getCoordinates().replace(), method.getArguments().toArray()); + return JavaTemplate.apply("System.out.printf(#{any()}, #{any()}, 0);", getCursor(), method.getCoordinates().replace(), method.getArguments().toArray()); } return super.visitMethodInvocation(method, executionContext); } @@ -277,9 +273,7 @@ void contextFreeRecursiveTypeParameters() { @Override public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { if ("o".equals(multiVariable.getVariables().getFirst().getSimpleName())) { - return JavaTemplate.builder("var o = #{any()};") - .build() - .apply(getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); + return JavaTemplate.apply("var o = #{any()};", getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); } return multiVariable; } @@ -317,9 +311,7 @@ void contextFreeSequenceTypeParameters() { @Override public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { if ("o".equals(multiVariable.getVariables().getFirst().getSimpleName())) { - return JavaTemplate.builder("var o = #{any()};") - .build() - .apply(getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); + return JavaTemplate.apply("var o = #{any()};", getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); } return multiVariable; } @@ -359,9 +351,7 @@ void contextFreeMultipleBoundParameters() { @Override public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { if ("o".equals(multiVariable.getVariables().getFirst().getSimpleName())) { - return JavaTemplate.builder("var o = #{any()};") - .build() - .apply(getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); + return JavaTemplate.apply("var o = #{any()};", getCursor(), multiVariable.getCoordinates().replace(), multiVariable.getVariables().getFirst().getInitializer()); } return multiVariable; } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateInstanceOfTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateInstanceOfTest.java index 01e8ffbe0fc..a8509912568 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateInstanceOfTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateInstanceOfTest.java @@ -479,13 +479,7 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) } List arguments = mi.getArguments(); - mi = JavaTemplate.builder("#{any(java.lang.String)}.formatted(#{any()})") - .build() - .apply( - updateCursor(mi), - mi.getCoordinates().replace(), - arguments.toArray() - ); + mi = JavaTemplate.apply("#{any(java.lang.String)}.formatted(#{any()})", updateCursor(mi), mi.getCoordinates().replace(), arguments.toArray()); return maybeAutoFormat(mi, mi.withArguments( ListUtils.map(arguments.subList(1, arguments.size()), (a, b) -> b.withPrefix(arguments.get(a + 1).getPrefix()))), ctx); diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateNamedTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateNamedTest.java index 3d042138598..34a9406bbd9 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateNamedTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateNamedTest.java @@ -33,15 +33,10 @@ void replaceSingleStatement() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitAssert(J.Assert anAssert, ExecutionContext p) { - return JavaTemplate.builder( - """ - if(#{name:any(int)} != #{}) { - #{name}++; - }""" - ) - .build() - .apply(getCursor(), anAssert.getCoordinates().replace(), - ((J.Binary) anAssert.getCondition()).getLeft(), "1"); + return JavaTemplate.apply(""" + if(#{name:any(int)} != #{}) { + #{name}++; + }""", getCursor(), anAssert.getCoordinates().replace(), ((J.Binary) anAssert.getCondition()).getLeft(), "1"); } })), java( diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java index c74e3cd6397..0805f294db5 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateSubstitutionsTest.java @@ -124,9 +124,7 @@ void annotation() { @Override public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) { if ("test".equals(method.getSimpleName())) { - return JavaTemplate.builder("#{} void test2() {}") - .build() - .apply(getCursor(), method.getCoordinates().replace(), method.getLeadingAnnotations().getFirst()); + return JavaTemplate.apply("#{} void test2() {}", getCursor(), method.getCoordinates().replace(), method.getLeadingAnnotations().getFirst()); } return method; } @@ -194,9 +192,7 @@ void block() { @Override public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) { var s = method.getBody().getStatements().getFirst(); - return JavaTemplate.builder("if(true) #{}") - .build() - .apply(getCursor(), s.getCoordinates().replace(), method.getBody()); + return JavaTemplate.apply("if(true) #{}", getCursor(), s.getCoordinates().replace(), method.getBody()); } }).withMaxCycles(1)), java( @@ -425,9 +421,7 @@ void anyIsGenericWithUnknownType() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { - return JavaTemplate.builder("System.out.println(#{any()})") - .build() - .apply(getCursor(), method.getCoordinates().replace(), method); + return JavaTemplate.apply("System.out.println(#{any()})", getCursor(), method.getCoordinates().replace(), method); } }).withMaxCycles(1)), java( @@ -457,9 +451,7 @@ void throwNewException() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitMethodInvocation(J.MethodInvocation methodInvocation, ExecutionContext executionContext) { - return JavaTemplate.builder("throw new RuntimeException()") - .build() - .apply(getCursor(), methodInvocation.getCoordinates().replace()); + return JavaTemplate.apply("throw new RuntimeException()", getCursor(), methodInvocation.getCoordinates().replace()); } })), java( diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java index 04949241ba7..717c4bf2a6a 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest.java @@ -110,9 +110,7 @@ void addParentheses() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitParentheses(J.Parentheses parens, ExecutionContext ctx) { - return JavaTemplate.builder("#{any()}") - .build() - .apply(getCursor(), parens.getCoordinates().replace(), parens.getTree()); + return JavaTemplate.apply("#{any()}", getCursor(), parens.getCoordinates().replace(), parens.getTree()); } })) .cycles(1) @@ -138,9 +136,7 @@ void addParenthesesToParameter() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitBinary(J.Binary binary, ExecutionContext ctx) { - return JavaTemplate.builder("#{any(int)} * 3") - .build() - .apply(getCursor(), binary.getCoordinates().replace(), binary); + return JavaTemplate.apply("#{any(int)} * 3", getCursor(), binary.getCoordinates().replace(), binary); } })) .cycles(1) @@ -209,9 +205,7 @@ public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations m return multiVariable; } J.VariableDeclarations.NamedVariable var0 = multiVariable.getVariables().getFirst(); - return JavaTemplate.builder("var #{} = #{any()};") - .build() - .apply(getCursor(), multiVariable.getCoordinates().replace(), var0.getSimpleName(), var0.getInitializer()); + return JavaTemplate.apply("var #{} = #{any()};", getCursor(), multiVariable.getCoordinates().replace(), var0.getSimpleName(), var0.getInitializer()); } })), java( @@ -399,18 +393,11 @@ public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext ct if (classDecl.getBody().getStatements().size() > 1) { return classDecl; } - return JavaTemplate.builder(""" + return JavaTemplate.apply(""" void m2() { #{any()} } - """ - ) - .build() - .apply( - getCursor(), - classDecl.getBody().getStatements().getFirst().getCoordinates().after(), - ((J.MethodDeclaration) classDecl.getBody().getStatements().getFirst()).getBody().getStatements().getFirst() - ); + """, getCursor(), classDecl.getBody().getStatements().getFirst().getCoordinates().after(), ((J.MethodDeclaration) classDecl.getBody().getStatements().getFirst()).getBody().getStatements().getFirst()); } })), java( @@ -595,9 +582,7 @@ void templatingWhileLoopCondition() { public J visitBinary(J.Binary binary, ExecutionContext ctx) { if (binary.getLeft() instanceof J.MethodInvocation) { var mi = (J.MethodInvocation) binary.getLeft(); - return JavaTemplate.builder("!#{any(java.util.List)}.isEmpty()") - .build() - .apply(getCursor(), mi.getCoordinates().replace(), mi.getSelect()); + return JavaTemplate.apply("!#{any(java.util.List)}.isEmpty()", getCursor(), mi.getCoordinates().replace(), mi.getSelect()); } else if (binary.getLeft() instanceof J.Unary) { return binary.getLeft(); } @@ -678,12 +663,7 @@ void replaceExpressionWithAnotherExpression() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitUnary(J.Unary unary, ExecutionContext ctx) { - return JavaTemplate.builder("#{any()}++") - .build().apply( - getCursor(), - unary.getCoordinates().replace(), - unary.getExpression() - ); + return JavaTemplate.apply("#{any()}++", getCursor(), unary.getCoordinates().replace(), unary.getExpression()); } }).withMaxCycles(1)), java( @@ -1017,9 +997,7 @@ void nestedEnums() { spec -> spec.recipe(toRecipe(() -> new JavaVisitor<>() { @Override public J visitBinary(J.Binary binary, ExecutionContext ctx) { - return JavaTemplate.builder("\"ab\"") - .build() - .apply(getCursor(), binary.getCoordinates().replace()); + return JavaTemplate.apply("\"ab\"", getCursor(), binary.getCoordinates().replace()); } })), java( @@ -1354,9 +1332,7 @@ void replaceMethodInChainFollowedByGenericTypeParameters() { @Override public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { if (new MethodMatcher("batch.StepBuilder create()").matches(method)) { - return JavaTemplate.builder("new StepBuilder()") - .build() - .apply(getCursor(), method.getCoordinates().replace()); + return JavaTemplate.apply("new StepBuilder()", getCursor(), method.getCoordinates().replace()); } return super.visitMethodInvocation(method, ctx); } @@ -1406,9 +1382,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu J.MethodInvocation mi = super.visitMethodInvocation(method, ctx); if (new MethodMatcher("Foo bar(..)").matches(mi) && mi.getArguments().getFirst() instanceof J.Binary) { - return JavaTemplate.builder("\"Hello, {}\", \"World!\"") - .build() - .apply(new Cursor(getCursor().getParent(), mi), mi.getCoordinates().replaceArguments()); + return JavaTemplate.apply("\"Hello, {}\", \"World!\"", new Cursor(getCursor().getParent(), mi), mi.getCoordinates().replaceArguments()); } return mi; } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest3Test.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest3Test.java index 53a9c96d8ab..f657688bcad 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest3Test.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest3Test.java @@ -40,9 +40,7 @@ void replacePackage() { @Override public J.Package visitPackage(J.Package pkg, ExecutionContext p) { if ("a".equals(pkg.getExpression().printTrimmed(getCursor()))) { - return JavaTemplate.builder("b") - .build() - .apply(getCursor(), pkg.getCoordinates().replace()); + return JavaTemplate.apply("b", getCursor(), pkg.getCoordinates().replace()); } return super.visitPackage(pkg, p); } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest4Test.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest4Test.java index ceacc1e8fef..453342dea76 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest4Test.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest4Test.java @@ -166,9 +166,7 @@ void replaceAndInterpolateMethodParameters() { public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext p) { { if ("test".equals(method.getSimpleName()) && method.getParameters().size() == 1) { - return JavaTemplate.builder("int n, #{}") - .build() - .apply(getCursor(), method.getCoordinates().replaceParameters(), method.getParameters().getFirst()); + return JavaTemplate.apply("int n, #{}", getCursor(), method.getCoordinates().replaceParameters(), method.getParameters().getFirst()); } return method; } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest6Test.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest6Test.java index b2033b75ca1..a7b1747d311 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest6Test.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest6Test.java @@ -243,9 +243,7 @@ void replaceThrows() { @Override public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext p) { if (method.getThrows() == null) { - return JavaTemplate.builder("Exception") - .build() - .apply(getCursor(), method.getCoordinates().replaceThrows()); + return JavaTemplate.apply("Exception", getCursor(), method.getCoordinates().replaceThrows()); } return super.visitMethodDeclaration(method, p); } diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest7Test.java b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest7Test.java index 1ffb8d42aac..8dabb3bb081 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest7Test.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/JavaTemplateTest7Test.java @@ -73,18 +73,13 @@ void methodDeclarationWithComment() { public J visitClassDeclaration(J.ClassDeclaration classDecl, ExecutionContext executionContext) { var cd = classDecl; if (cd.getBody().getStatements().isEmpty()) { - cd = JavaTemplate.builder( - //language=java - """ - /** - * comment - */ - void foo() { - } - """ - ) - .build() - .apply(getCursor(), cd.getBody().getCoordinates().firstStatement()); + cd = JavaTemplate.apply(""" + /** + * comment + */ + void foo() { + } + """, getCursor(), cd.getBody().getCoordinates().firstStatement()); } return cd; } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java b/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java index 48ad75f66e7..09e5547806f 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java @@ -175,7 +175,7 @@ public J parameter(int i) { } public static J2 apply(String template, Cursor scope, JavaCoordinates coordinates, Object... parameters) { - return builder(template).build().apply(scope, coordinates, parameters); + return JavaTemplate.apply(template, scope, coordinates, parameters); } public static Builder builder(String code) { From f79ade29ae1d7b7334fce189b40beb7c73652c4c Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Tue, 31 Mar 2026 21:36:35 +0200 Subject: [PATCH 2/2] Fix StackOverflowError in static JavaTemplate.apply() The static apply() method was calling itself recursively instead of delegating to builder(template).build().apply(). --- .../src/main/java/org/openrewrite/java/JavaTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java b/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java index 09e5547806f..48ad75f66e7 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/JavaTemplate.java @@ -175,7 +175,7 @@ public J parameter(int i) { } public static J2 apply(String template, Cursor scope, JavaCoordinates coordinates, Object... parameters) { - return JavaTemplate.apply(template, scope, coordinates, parameters); + return builder(template).build().apply(scope, coordinates, parameters); } public static Builder builder(String code) {