net.autobuilder.core.Util Maven / Gradle / Ivy
package net.autobuilder.core;
import static java.lang.Character.isLowerCase;
import static java.lang.Character.isUpperCase;
import static java.lang.Character.toLowerCase;
import static java.lang.Character.toUpperCase;
import static java.util.Collections.emptySet;
import static javax.lang.model.element.Modifier.FINAL;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.WildcardTypeName;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.SimpleTypeVisitor8;
final class Util {
private static final SimpleTypeVisitor8 SUBTYPE =
new SimpleTypeVisitor8() {
@Override
public TypeName visitDeclared(DeclaredType declaredType, Void _null) {
if (declaredType.asElement().getModifiers().contains(FINAL)) {
return TypeName.get(declaredType);
}
return WildcardTypeName.subtypeOf(TypeName.get(declaredType));
}
@Override
public TypeName visitTypeVariable(TypeVariable typeVariable, Void _null) {
return WildcardTypeName.subtypeOf(TypeName.get(typeVariable));
}
};
private static final SimpleTypeVisitor8 AS_DECLARED =
new SimpleTypeVisitor8() {
@Override
public DeclaredType visitDeclared(DeclaredType declaredType, Void _null) {
return declaredType;
}
};
private final ProcessingEnvironment processingEnv;
Util(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}
static TypeName[] typeArgumentSubtypes(VariableElement variableElement) {
DeclaredType declaredType = variableElement.asType().accept(AS_DECLARED, null);
if (declaredType == null) {
throw new AssertionError();
}
return declaredType.getTypeArguments()
.stream()
.map(Util::subtypeOf)
.toArray(TypeName[]::new);
}
private static TypeName subtypeOf(TypeMirror typeMirror) {
TypeName typeName = typeMirror.accept(SUBTYPE, null);
return typeName != null ? typeName : TypeName.get(typeMirror);
}
static String upcase(String s) {
if (s.isEmpty() || isUpperCase(s.charAt(0))) {
return s;
}
return toUpperCase(s.charAt(0)) + s.substring(1);
}
static String downcase(String s) {
if (s.isEmpty() || isLowerCase(s.charAt(0))) {
return s;
}
return toLowerCase(s.charAt(0)) + s.substring(1);
}
static Collector, Boolean> isDistinct() {
return new Collector, Boolean>() {
@Override
public Supplier> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer, E> accumulator() {
return List::add;
}
@Override
public BinaryOperator> combiner() {
return (left, right) -> {
left.addAll(right);
return left;
};
}
@Override
public Function, Boolean> finisher() {
return elements -> {
Set set = new HashSet<>();
for (E element : elements) {
if (!set.add(element)) {
return false;
}
}
return true;
};
}
@Override
public Set characteristics() {
return emptySet();
}
};
}
static Collector, CodeBlock> joinCodeBlocks(String delimiter) {
return new Collector, CodeBlock>() {
@Override
public Supplier> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer, CodeBlock> accumulator() {
return List::add;
}
@Override
public BinaryOperator> combiner() {
return (left, right) -> {
left.addAll(right);
return left;
};
}
@Override
public Function, CodeBlock> finisher() {
return blocks -> {
CodeBlock.Builder builder = CodeBlock.builder();
if (blocks.isEmpty()) {
return builder.build();
}
builder.add(blocks.get(0));
blocks.stream().skip(1).forEach(block ->
builder.add(delimiter).add(block));
return builder.build();
};
}
@Override
public Set characteristics() {
return emptySet();
}
};
}
TypeElement typeElement(ClassName className) {
return processingEnv.getElementUtils().getTypeElement(
className.toString());
}
}