io.slugstack.rewritejavarecipes.internal.example.hideutility.HideUtilityClassConstructorVisitorUsingStreamMappingExample Maven / Gradle / Ivy
Show all versions of rewrite-java-recipes Show documentation
package io.slugstack.rewritejavarecipes.internal.example.hideutility;
import org.openrewrite.Incubating;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.JavaIsoVisitor;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.Statement;
import java.util.List;
import java.util.stream.Collectors;
@SuppressWarnings("unused")
@Incubating(since = "7.0.0")
public class HideUtilityClassConstructorVisitorUsingStreamMappingExample extends JavaIsoVisitor
{
@SuppressWarnings("unused")
public HideUtilityClassConstructorVisitorUsingStreamMappingExample() {
}
@Override
public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, P p) {
J.ClassDeclaration c = super.visitClassDeclaration(classDecl, p);
if (isUtilityClass(c)) {
List statements = c.getBody().getStatements();
// iterate over each Method Declaration and update proper access modifiers
statements = statements.stream().map(J.MethodDeclaration.class::cast)
// note we don't use filter ops on the stream.
// .filter(J.MethodDecl::isConstructor)
// filtering the stream wouldn't return all statements of the class body.
// .filter(md -> !md.hasModifier(J.Modifier.Type.Private))
.map(md -> {
// we only care about tightening constructors' access, and only constructors
// which are missing 'private'
if (md.isConstructor() && !md.hasModifier(J.Modifier.Type.Private)) {
// get the method's modifiers. check each modifier. if the modifier is PUBLIC,
// update it to be PRIVATE. if the modifier is anything else, just leave the
// modifier untouched
md = md.withModifiers(ListUtils.map(md.getModifiers(),
mod -> mod.getType() == J.Modifier.Type.Public
? mod.withType(J.Modifier.Type.Private)
: mod));
}
return md;
}).collect(Collectors.toList());
c = c.withBody(c.getBody().withStatements(statements));
}
return c;
}
/**
* A utility class contains only static methods or fields in their API, and does
* not have a public constructor.
*/
private boolean isUtilityClass(J.ClassDeclaration c) {
return c.getBody().getStatements().stream().allMatch(s -> s instanceof J.MethodDeclaration
&& (((J.MethodDeclaration) s).isConstructor() || ((J.MethodDeclaration) s).hasModifier(J.Modifier.Type.Static)));
}
}