com.github.anhem.testpopulator.internal.object.ObjectBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of test-populator Show documentation
Show all versions of test-populator Show documentation
Populate java classes with fixed or random data using reflection. Facilitates the creation of objects in tests.
The newest version!
package com.github.anhem.testpopulator.internal.object;
import com.github.anhem.testpopulator.exception.ObjectException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.github.anhem.testpopulator.PopulateFactory.BUILDER_METHOD;
import static com.github.anhem.testpopulator.internal.util.ObjectBuilderUtil.*;
public class ObjectBuilder {
public static final String NULL = "null";
public static final String PSF = "public static final";
private static final String NEW_OBJECT_WITH_ARGUMENTS = "%s %s %s = new %s(%s);";
private static final String NEW_OBJECT = "%s %s %s = new %s();";
private static final String BUILDER = "%s %s %s = %s.%s()";
private static final String NEW_TYPED_OBJECT = "%s %s<%s> %s = new %s<>();";
private static final String SET_OF = "%s %s<%s> %s = Set.of(%s);";
private static final String LIST_OF = "%s %s<%s> %s = List.of(%s);";
private static final String MAP_OF = "%s %s<%s> %s = Map.of(%s);";
private static final String NEW_ARRAY = "%s %s[] %s = new %s[]{%s};";
private static final String NEW_VALUE = "%s %s %s = %s;";
private static final String ARGUMENT_DELIMITER = ", ";
private Class clazz;
private final String name;
private final BuildType buildType;
private final List children = new ArrayList<>();
private final int expectedChildren;
private ObjectBuilder parent;
private String value;
public ObjectBuilder(Class clazz, String name, BuildType buildType, int expectedChildren) {
this.clazz = clazz;
this.name = name;
this.buildType = buildType;
this.expectedChildren = expectedChildren;
}
public ObjectBuilder(String name, BuildType buildType, int expectedChildren) {
this.name = name;
this.buildType = buildType;
this.expectedChildren = expectedChildren;
}
public void addChild(ObjectBuilder child) {
children.add(child);
}
public List getChildren() {
return children;
}
public boolean hasAllChildren() {
return expectedChildren == children.size();
}
public Class getClazz() {
return clazz;
}
public String getName() {
return name;
}
public BuildType getBuildType() {
return buildType;
}
public ObjectBuilder getParent() {
return parent;
}
public void setParent(ObjectBuilder parent) {
this.parent = parent;
}
public void setValue(String value) {
this.value = value;
}
public ObjectResult build() {
String packageName = getPackageName(clazz);
String className = formatClassName(clazz);
Set imports = new HashSet<>();
Set staticImports = new HashSet<>();
getImports(imports, staticImports);
List objects = buildByBuildType();
return new ObjectResult(packageName, className, imports, staticImports, objects);
}
private void getImports(Set imports, Set staticImports) {
addImport(clazz, value, imports, staticImports);
children.forEach(objectBuilder -> objectBuilder.getImports(imports, staticImports));
}
private List buildByBuildType() {
switch (buildType) {
case CONSTRUCTOR:
return buildConstructor();
case SETTER:
return buildSetter();
case BUILDER:
return buildBuilder();
case METHOD:
return buildMethod();
case SET:
return buildSet();
case SET_OF:
return buildSetOf();
case LIST:
return buildList();
case LIST_OF:
return buildListOf();
case MAP:
return buildMap();
case MAP_OF:
return buildMapOf();
case ARRAY:
return buildArray();
case VALUE:
return buildValue();
default:
throw new ObjectException(String.format("Invalid buildType %s", buildType));
}
}
private Stream buildChildren() {
return children.stream()
.filter(child -> !isBasicValue(child))
.map(ObjectBuilder::buildByBuildType)
.flatMap(Collection::stream);
}
private List buildConstructor() {
return concatenate(buildChildren(),
Stream.of(String.format(NEW_OBJECT_WITH_ARGUMENTS, PSF, clazz.getSimpleName(), name, clazz.getSimpleName(), buildArguments())))
.collect(Collectors.toList());
}
private List buildSetter() {
return concatenate(
buildChildren(),
Stream.of(String.format(NEW_OBJECT, PSF, clazz.getSimpleName(), name, clazz.getSimpleName())),
startStaticBlock(),
createMethods(),
endStaticBlock()
).collect(Collectors.toList());
}
private List buildBuilder() {
return concatenate(
buildChildren(),
Stream.of(String.format(BUILDER, PSF, clazz.getSimpleName(), name, clazz.getSimpleName(), BUILDER_METHOD)),
createMethods(),
endBuilder()
).collect(Collectors.toList());
}
private List buildMethod() {
return buildChildren().collect(Collectors.toList());
}
private List buildSet() {
return buildCollection();
}
private List buildSetOf() {
return concatenate(
buildChildren(),
Stream.of(String.format(SET_OF, PSF, clazz.getSimpleName(), formatTypes(), name, getNullableArguments(buildArguments()))))
.collect(Collectors.toList());
}
private List buildList() {
return buildCollection();
}
private List buildListOf() {
return concatenate(
buildChildren(),
Stream.of(String.format(LIST_OF, PSF, clazz.getSimpleName(), formatTypes(), name, getNullableArguments(buildArguments()))))
.collect(Collectors.toList());
}
private List buildMap() {
return buildCollection();
}
private List buildMapOf() {
return concatenate(
buildChildren(),
Stream.of(String.format(MAP_OF, PSF, clazz.getSimpleName(), formatTypes(), name, getNullableArguments(buildArguments()))))
.collect(Collectors.toList());
}
private List buildArray() {
return concatenate(
buildChildren(),
Stream.of(String.format(NEW_ARRAY, PSF, clazz.getSimpleName(), name, clazz.getSimpleName(), buildArguments())))
.collect(Collectors.toList());
}
private List buildCollection() {
if (collectionHasNullValues(this)) {
return concatenate(
buildChildren(),
Stream.of(String.format(NEW_TYPED_OBJECT, PSF, clazz.getSimpleName(), formatTypes(), name, clazz.getSimpleName())))
.collect(Collectors.toList());
}
return concatenate(
buildChildren(),
Stream.of(String.format(NEW_TYPED_OBJECT, PSF, clazz.getSimpleName(), formatTypes(), name, clazz.getSimpleName())),
startStaticBlock(),
createMethods(),
endStaticBlock()
).collect(Collectors.toList());
}
private List buildValue() {
if (isNullValue()) {
return List.of();
}
return List.of(String.format(NEW_VALUE, PSF, clazz.getSimpleName(), name, value));
}
public boolean isNullValue() {
return value != null && value.equals(NULL);
}
private Stream createMethods() {
return children.stream()
.map(child -> buildType == BuildType.BUILDER ?
String.format(".%s(%s)", child.getName(), child.buildArguments()) :
String.format("%s.%s(%s);", name, child.getName(), child.buildArguments()));
}
private static String getNullableArguments(String buildArguments) {
return Arrays.asList(buildArguments.split(ARGUMENT_DELIMITER)).contains(NULL) ? "" : buildArguments;
}
private String buildArguments() {
return children.stream()
.map(child -> {
if (child.isNullValue()) {
return List.of(NULL);
}
if (isBasicValue(child)) {
return child.buildInlineArgument();
}
return List.of(child.getName());
}).flatMap(Collection::stream)
.collect(Collectors.joining(ARGUMENT_DELIMITER));
}
private List buildInlineArgument() {
return List.of(this.value);
}
private String formatTypes() {
return children.stream()
.map(child -> {
if (child.getClazz() == null) {
return child.formatTypes();
}
if (child.getBuildType().isParameterizedType()) {
return String.format("%s<%s>", child.getClazz().getSimpleName(), child.formatTypes());
} else {
return child.getClazz().getSimpleName();
}
}).collect(Collectors.joining(ARGUMENT_DELIMITER));
}
}