package com.lambdaworks.apigenerator; import java.io.File; import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; import com.lambdaworks.redis.internal.LettuceSets; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.ast.type.ReferenceType; import com.github.javaparser.ast.type.Type; /** * Create async API based on the templates. * * @author Mark Paluch */ @RunWith(Parameterized.class) public class CreateAsyncNodeSelectionClusterApi { private Set<String> FILTER_METHODS = LettuceSets.unmodifiableSet("shutdown", "debugOom", "debugSegfault", "digest", "close", "isOpen", "BaseRedisCommands.reset", "readOnly", "readWrite"); private CompilationUnitFactory factory; @Parameterized.Parameters(name = "Create {0}") public static List<Object[]> arguments() { List<Object[]> result = new ArrayList<>(); for (String templateName : Constants.TEMPLATE_NAMES) { if (templateName.contains("Transactional") || templateName.contains("Sentinel")) { continue; } result.add(new Object[] { templateName }); } return result; } /** * @param templateName */ public CreateAsyncNodeSelectionClusterApi(String templateName) { String targetName = templateName.replace("Commands", "AsyncCommands").replace("Redis", "NodeSelection"); File templateFile = new File(Constants.TEMPLATES, "com/lambdaworks/redis/api/" + templateName + ".java"); String targetPackage = "com.lambdaworks.redis.cluster.api.async"; // todo: remove AutoCloseable from BaseNodeSelectionAsyncCommands factory = new CompilationUnitFactory(templateFile, Constants.SOURCES, targetPackage, targetName, commentMutator(), methodTypeMutator(), methodFilter(), importSupplier(), null, null); } /** * Mutate type comment. * * @return */ protected Function<String, String> commentMutator() { return s -> s.replaceAll("\\$\\{intent\\}", "Asynchronous executed commands on a node selection") + "* @generated by " + getClass().getName() + "\r\n "; } /** * Mutate type to async result. * * @return */ protected Predicate<MethodDeclaration> methodFilter() { return method -> { ClassOrInterfaceDeclaration classOfMethod = (ClassOrInterfaceDeclaration) method.getParentNode(); if (FILTER_METHODS.contains(method.getName()) || FILTER_METHODS.contains(classOfMethod.getName() + "." + method.getName())) { return false; } return true; }; } /** * Mutate type to async result. * * @return */ protected Function<MethodDeclaration, Type> methodTypeMutator() { return method -> { ClassOrInterfaceDeclaration classOfMethod = (ClassOrInterfaceDeclaration) method.getParentNode(); if (FILTER_METHODS.contains(method.getName()) || FILTER_METHODS.contains(classOfMethod.getName() + "." + method.getName())) { return method.getType(); } String typeAsString = method.getType().toStringWithoutComments().trim(); if (typeAsString.equals("void")) { typeAsString = "Void"; } return new ReferenceType(new ClassOrInterfaceType("AsyncExecutions<" + typeAsString + ">")); }; } /** * Supply additional imports. * * @return */ protected Supplier<List<String>> importSupplier() { return () -> Collections.singletonList("com.lambdaworks.redis.RedisFuture"); } @Test public void createInterface() throws Exception { factory.createInterface(); } }