Skip to content

Commit

Permalink
Merge pull request #36 from Gmugra/27_Compiler_config-class_generation
Browse files Browse the repository at this point in the history
#27 : Compiler: config-class generation -> ConcurrentHashMap
  • Loading branch information
Gmugra committed Apr 24, 2021
2 parents 2ba79a3 + 8100c39 commit 80ebde7
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.cactusthorn.config.compiler;

import static net.cactusthorn.config.compiler.ConfigGenerator.METHOD_ENUM_NAME;
import static net.cactusthorn.config.compiler.ConfigGenerator.METHOD_ENUM;

import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
Expand Down Expand Up @@ -36,21 +39,12 @@ public final class ConfigBuilderGenerator extends Generator {
@Override JavaFile generate() {
TypeName superClass = ParameterizedTypeName.get(CONFIG_BUILDER, configClass);
TypeSpec.Builder classBuilder = classBuilder().superclass(superClass);
addEnum(classBuilder);
addKey(classBuilder);
addDefault(classBuilder);
addConstructor(classBuilder);
addBuild(classBuilder);

return JavaFile.builder(packageName(), classBuilder.build()).build();
}

private static final String METHOD_ENUM_NAME = "Method";

private void addEnum(TypeSpec.Builder classBuilder) {
TypeSpec.Builder enumBuilder = TypeSpec.enumBuilder(METHOD_ENUM_NAME).addModifiers(Modifier.PRIVATE);
methodsInfo().forEach(mi -> enumBuilder.addEnumConstant(mi.name()));
classBuilder.addType(enumBuilder.build());
return JavaFile.builder(packageName(), classBuilder.build()).addStaticImport(configClass, METHOD_ENUM_NAME).build();
}

private static final ClassName MAP = ClassName.get(Map.class);
Expand All @@ -60,7 +54,7 @@ private void addEnum(TypeSpec.Builder classBuilder) {
private static final String KEYS_MAP_NAME = "KEYS";

private void addKey(TypeSpec.Builder classBuilder) {
ClassName methodsEnumName = ClassName.get(packageName(), className() + '.' + METHOD_ENUM_NAME);
ClassName methodsEnumName = ClassName.get(packageName(), METHOD_ENUM_NAME);
TypeName mapTypeName = ParameterizedTypeName.get(MAP, methodsEnumName, STRING);

FieldSpec fieldSpec = FieldSpec.builder(mapTypeName, KEYS_MAP_NAME, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).build();
Expand All @@ -76,7 +70,7 @@ private void addKey(TypeSpec.Builder classBuilder) {
private static final String DEFAULTS_MAP_NAME = "DEFAULTS";

private void addDefault(TypeSpec.Builder classBuilder) {
ClassName methodsEnumName = ClassName.get(packageName(), className() + '.' + METHOD_ENUM_NAME);
ClassName methodsEnumName = ClassName.get(packageName(), METHOD_ENUM_NAME);
TypeName mapTypeName = ParameterizedTypeName.get(MAP, methodsEnumName, STRING);

FieldSpec fieldSpec = FieldSpec.builder(mapTypeName, DEFAULTS_MAP_NAME, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).build();
Expand All @@ -103,11 +97,11 @@ private void addBuild(TypeSpec.Builder classBuilder) {
MethodSpec.Builder buildBuilder = MethodSpec.methodBuilder("build").addModifiers(Modifier.PUBLIC).addAnnotation(Override.class)
.returns(configClass);

methodsInfo().forEach(mi -> buildBuilder.addStatement("$T $L = $L", mi.returnTypeName(), mi.name(), convert(mi)));
buildBuilder.addStatement("Map<$T,$T> values = new $T<>()", METHOD_ENUM, Object.class, HashMap.class);

String parameters = methodsInfo().stream().map(mi -> mi.name()).collect(Collectors.joining(", "));
methodsInfo().forEach(mi -> buildBuilder.addStatement("values.put($L.$L, $L)", METHOD_ENUM_NAME, mi.name(), convert(mi)));

classBuilder.addMethod(buildBuilder.addStatement("return new $T($L)", configClass, parameters).build());
classBuilder.addMethod(buildBuilder.addStatement("return new $T(values)", configClass).build());
}

private CodeBlock convert(MethodInfo mi) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package net.cactusthorn.config.compiler;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;

import net.cactusthorn.config.compiler.methodvalidator.MethodInfo;
Expand All @@ -25,7 +30,8 @@ final class ConfigGenerator extends Generator {

@Override JavaFile generate() {
TypeSpec.Builder classBuilder = classBuilder().addSuperinterface(interfaceElement().asType());
methodsInfo().forEach(mi -> addField(classBuilder, mi));
addEnum(classBuilder);
addValues(classBuilder);
addConstructor(classBuilder);
methodsInfo().forEach(mi -> addGetter(classBuilder, mi));
addHashCode(classBuilder);
Expand All @@ -35,15 +41,35 @@ final class ConfigGenerator extends Generator {
return JavaFile.builder(packageName(), classBuilder.build()).build();
}

private void addField(TypeSpec.Builder classBuilder, MethodInfo methodInfo) {
FieldSpec fieldSpec = FieldSpec.builder(methodInfo.returnTypeName(), methodInfo.name(), Modifier.PRIVATE, Modifier.FINAL).build();
static final String METHOD_ENUM_NAME = "Method";
static final ClassName METHOD_ENUM = ClassName.get("", METHOD_ENUM_NAME);

private void addEnum(TypeSpec.Builder classBuilder) {
TypeSpec.Builder enumBuilder = TypeSpec.enumBuilder(METHOD_ENUM_NAME).addModifiers(Modifier.PUBLIC);
methodsInfo().forEach(mi -> enumBuilder.addEnumConstant(mi.name()));
classBuilder.addType(enumBuilder.build());
}

private static final ClassName CONCURRENTHASHMAP = ClassName.get(ConcurrentHashMap.class);
private static final ClassName OBJECT = ClassName.get(Object.class);
private static final TypeName VALUES_MAP = ParameterizedTypeName.get(CONCURRENTHASHMAP, METHOD_ENUM, OBJECT);

private static final String VALUES_ATTR = "VALUES";

private void addValues(TypeSpec.Builder classBuilder) {
FieldSpec fieldSpec = FieldSpec.builder(VALUES_MAP, VALUES_ATTR, Modifier.PRIVATE, Modifier.FINAL)
.initializer("new ConcurrentHashMap<>()").build();
classBuilder.addField(fieldSpec);
}

private static final ClassName MAP = ClassName.get(Map.class);
private static final TypeName VALUES_PARAM_MAP = ParameterizedTypeName.get(MAP, METHOD_ENUM, OBJECT);

private static final String VALUES_PARAM = "values";

private void addConstructor(TypeSpec.Builder classBuilder) {
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder();
methodsInfo().forEach(mi -> constructorBuilder.addParameter(mi.returnTypeName(), mi.name(), Modifier.FINAL));
methodsInfo().forEach(mi -> constructorBuilder.addStatement("this.$N = $N", mi.name(), mi.name()));
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder().addParameter(VALUES_PARAM_MAP, VALUES_PARAM, Modifier.FINAL)
.addStatement("$L.putAll($L)", VALUES_ATTR, VALUES_PARAM);
classBuilder.addMethod(constructorBuilder.build());
}

Expand All @@ -54,14 +80,14 @@ private void addGetter(TypeSpec.Builder classBuilder, MethodInfo methodInfo) {
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.returns(methodInfo.returnTypeName())
.addStatement("return $N", methodInfo.name())
.addStatement("return ($T)VALUES.get(Method.$L)", methodInfo.returnTypeName(), methodInfo.name())
.build();
// @formatter:on
classBuilder.addMethod(getter);
}

private void addHashCode(TypeSpec.Builder classBuilder) {
String parameters = methodsInfo().stream().map(mi -> mi.name()).collect(Collectors.joining(", "));
String parameters = methodsInfo().stream().map(mi -> mi.name() + "()").collect(Collectors.joining(", "));
// @formatter:off
MethodSpec hashCode =
MethodSpec.methodBuilder("hashCode")
Expand All @@ -74,7 +100,7 @@ private void addHashCode(TypeSpec.Builder classBuilder) {
classBuilder.addMethod(hashCode);
}

private static final String BUF_NAME = "buf$$buf";
private static final String BUF_NAME = "buf";

private void addToString(TypeSpec.Builder classBuilder) {
// @formatter:off
Expand All @@ -84,17 +110,17 @@ private void addToString(TypeSpec.Builder classBuilder) {
.addAnnotation(Override.class)
.returns(String.class)
.addStatement("$T $L = new $T()", StringBuilder.class, BUF_NAME, StringBuilder.class)
.addStatement("$L.append($S)", BUF_NAME, "[");
.addStatement("$L.append('[')", BUF_NAME);
// @formatter:on
for (int i = 0; i < methodsInfo().size(); i++) {
if (i != 0) {
toStringBuilder.addStatement("$L.append($S)", BUF_NAME, ", ");
}
MethodInfo mi = methodsInfo().get(i);
toStringBuilder
.addStatement("$L.append($S).append($S).append($T.valueOf($L))", BUF_NAME, mi.name(), "=", String.class, mi.name());
toStringBuilder.addStatement("$L.append($L.$L).append('=').append($T.valueOf($L.get($L.$L)))", BUF_NAME, METHOD_ENUM, mi.name(),
String.class, VALUES_ATTR, METHOD_ENUM, mi.name());
}
toStringBuilder.addStatement("$L.append($S)", BUF_NAME, "]");
toStringBuilder.addStatement("$L.append(']')", BUF_NAME);
toStringBuilder.addStatement("return $L.toString()", BUF_NAME);
classBuilder.addMethod(toStringBuilder.build());
}
Expand All @@ -113,9 +139,9 @@ private void addEquals(TypeSpec.Builder classBuilder) {
// @formatter:on
methodsInfo().forEach(mi -> {
if (mi.returnTypeName().isPrimitive()) {
equalsBuilder.addStatement("if (this.$L != other.$L()) return false", mi.name(), mi.name());
equalsBuilder.addStatement("if (this.$L() != other.$L()) return false", mi.name(), mi.name());
} else {
equalsBuilder.addStatement("if (!this.$L.equals(other.$L())) return false", mi.name(), mi.name());
equalsBuilder.addStatement("if (!this.$L().equals(other.$L())) return false", mi.name(), mi.name());
}
});
equalsBuilder.addStatement("return true");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import static org.junit.jupiter.api.Assertions.*;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.TreeSet;
import java.util.UUID;
Expand All @@ -17,34 +19,20 @@ public class GonfigGeneratedTest {
private static AllCorrect config2;

@BeforeAll static void setUp() {
// @formatter:off
config = new Config$$AllCorrect(
new StringBuilder("ABC"),
125d,
AllCorrect.FromStringEnum.BBB,
124,
Optional.empty(),
new HashSet<>(Arrays.asList(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d"))),
AllCorrect.SimpleEnum.AAA,
new TreeSet<>(Arrays.asList(126f)),
"SI",
Optional.of(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d")),
"simpleString"
);
config2 = new Config$$AllCorrect(
new StringBuilder("ABC"),
125d,
AllCorrect.FromStringEnum.BBB,
124,
Optional.empty(),
new HashSet<>(Arrays.asList(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d"))),
AllCorrect.SimpleEnum.AAA,
new TreeSet<>(Arrays.asList(126f)),
"SI",
Optional.of(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d")),
"simpleString"
);
// @formatter:on
Map<Config$$AllCorrect.Method, Object> v1 = new HashMap<>();
v1.put(Config$$AllCorrect.Method.buf, new StringBuilder("ABC"));
v1.put(Config$$AllCorrect.Method.ddd, 125d);
v1.put(Config$$AllCorrect.Method.fromStringEnum, AllCorrect.FromStringEnum.BBB);
v1.put(Config$$AllCorrect.Method.intValue, 124);
v1.put(Config$$AllCorrect.Method.list, Optional.empty());
v1.put(Config$$AllCorrect.Method.set, new HashSet<>(Arrays.asList(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d"))));
v1.put(Config$$AllCorrect.Method.simpleEnum, AllCorrect.SimpleEnum.AAA);
v1.put(Config$$AllCorrect.Method.sorted, new TreeSet<>(Arrays.asList(126f)));
v1.put(Config$$AllCorrect.Method.superInterface, "SI");
v1.put(Config$$AllCorrect.Method.uuid, Optional.of(UUID.fromString("46400000-8cc0-11bd-b43e-10d46e4ef14d")));
v1.put(Config$$AllCorrect.Method.value, "simpleString");
config = new Config$$AllCorrect(v1);
config2 = new Config$$AllCorrect(v1);
}

@Test public void toStr() {
Expand All @@ -58,7 +46,7 @@ public class GonfigGeneratedTest {
}

@Test public void hash() {
assertNotEquals(config.hashCode(), config2.hashCode());
assertEquals(config.hashCode(), config2.hashCode());
}

@Test public void buf() {
Expand Down

0 comments on commit 80ebde7

Please sign in to comment.