package org.inferred.freebuilder.processor.util.feature; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Booleans; import com.google.common.primitives.Bytes; import com.google.common.primitives.Chars; import com.google.common.primitives.Doubles; import com.google.common.primitives.Floats; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import com.google.common.primitives.Shorts; import org.inferred.freebuilder.processor.util.Shading; import org.inferred.freebuilder.processor.util.SourceBuilder; import java.util.Arrays; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; /** * Whether the Guava library is available or not. Defaults to {@link #UNAVAILABLE} in tests. */ public enum GuavaLibrary implements Feature<GuavaLibrary> { AVAILABLE("Guava"), UNAVAILABLE("No Guava"); /** * Constant to pass to {@link SourceBuilder#feature(FeatureType)} to get the current status of * {@link GuavaLibrary}. */ public static final FeatureType<GuavaLibrary> GUAVA = new FeatureType<GuavaLibrary>() { @Override protected GuavaLibrary testDefault(FeatureSet features) { return UNAVAILABLE; } @Override protected GuavaLibrary forEnvironment(ProcessingEnvironment env, FeatureSet features) { String name = Shading.unshadedName(ImmutableList.class.getName()); TypeElement element = env.getElementUtils().getTypeElement(name); return (element != null) ? AVAILABLE : UNAVAILABLE; } }; private final String humanReadableFormat; GuavaLibrary(String humanReadableFormat) { this.humanReadableFormat = humanReadableFormat; } public boolean isAvailable() { return this != UNAVAILABLE; } private static Class<?> primitiveUtils(TypeMirror elementType) { switch (elementType.getKind()) { case BOOLEAN: return Booleans.class; case BYTE: return Bytes.class; case CHAR: return Chars.class; case DOUBLE: return Doubles.class; case FLOAT: return Floats.class; case INT: return Ints.class; case LONG: return Longs.class; case SHORT: return Shorts.class; default: throw new IllegalArgumentException("Unexpected primitive type " + elementType); } } /** * Returns a type with an {@code asList} method suitable for an array of {@code elementType} * elements, if one exists. * * <p>For non-primitive element types, this is just {@link Arrays}. For primitive element types, * it will be one of the Guava utility classes like {@link Ints}, if Guava is available. */ public Optional<Class<?>> arrayUtils(TypeMirror elementType) { if (!elementType.getKind().isPrimitive()) { return Optional.<Class<?>>of(Arrays.class); } else if (isAvailable()) { return Optional.<Class<?>>fromNullable(primitiveUtils(elementType)); } else { return Optional.absent(); } } @Override public String toString() { return humanReadableFormat; } }