io.jstach.rainbowgum.apt.prism.DefaultParameterPrism Maven / Gradle / Ivy
package io.jstach.rainbowgum.apt.prism;
import java.util.Map;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import org.eclipse.jdt.annotation.Nullable;
/**
* A Prism representing an {@code @io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter} annotation.
*/
public class DefaultParameterPrism {
/** store prism value of value */
private @Nullable String _value;
/**
* Qualified class name of annotation.
*/
public static final String PRISM_ANNOTATION_TYPE = "io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter";
/**
* An instance of the Values inner class whose
* methods return the AnnotationValues used to build this prism.
* Primarily intended to support using Messager.
*/
public final Values values;
/**
* Return a prism representing the {@code @io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter} annotation on 'e'.
* similar to {@code e.getAnnotation(io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter.class)} except that
* an instance of this class rather than an instance of {@code io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter}
* is returned.
* @param e element.
* @return prism for element.
*/
public static @Nullable DefaultParameterPrism getInstanceOn(Element e) {
AnnotationMirror m = getMirror(PRISM_ANNOTATION_TYPE, e);
if(m == null) return null;
return getInstance(m);
}
/**
* Return a prism of the {@code @io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter} annotation whose mirror is mirror.
* @param mirror mirror.
* @return prism for mirror
*/
public static DefaultParameterPrism getInstance(AnnotationMirror mirror) {
String mirrorType = mirror.getAnnotationType().toString();
if(!PRISM_ANNOTATION_TYPE.equals(mirrorType)) {
throw new java.lang.IllegalArgumentException("expected: " + PRISM_ANNOTATION_TYPE + " got: " + mirrorType);
}
return new DefaultParameterPrism(mirror);
}
private DefaultParameterPrism(AnnotationMirror mirror) {
for(var e : mirror.getElementValues().entrySet()) {
memberValues.put(e.getKey().getSimpleName().toString(), e.getValue());
}
for(ExecutableElement member : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
var defaultValue = member.getDefaultValue();
if (defaultValue == null) continue;
defaults.put(member.getSimpleName().toString(), defaultValue);
}
_value = getValue("value",String.class);
this.values = new Values(memberValues);
this.mirror = mirror;
this.isValid = valid;
}
/**
* Returns a String representing the value of the {@code java.lang.String value()} member of the Annotation.
* @return prism value.
* @see io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter#value()
*/
public String value() { return requireMember(_value); }
/**
* Determine whether the underlying AnnotationMirror has no errors.
* True if the underlying AnnotationMirror has no errors.
* When true is returned, none of the methods will return null.
* When false is returned, a least one member will either return null, or another
* prism that is not valid.
*/
public final boolean isValid;
/**
* The underlying AnnotationMirror of the annotation
* represented by this Prism.
* Primarily intended to support using Messager.
*/
public final AnnotationMirror mirror;
/**
* A class whose members corespond to those of io.jstach.rainbowgum.annotation.LogConfigurable.DefaultParameter
* but which each return the AnnotationValue corresponding to
* that member in the model of the annotations. Returns null for
* defaulted members. Used for Messager, so default values are not useful.
*/
public static class Values {
private Map values;
private Values(Map values) {
this.values = values;
}
/**
* Return the AnnotationValue corresponding to the value()
* member of the annotation, or null when the default value is implied.
* @return annotation value.
*/
public @Nullable AnnotationValue value(){ return values.get("value");}
}
private Map defaults = new java.util.HashMap<>();
private Map memberValues = new java.util.HashMap<>();
private boolean valid = true;
private @Nullable T getValue(String name, Class clazz) {
@Nullable T result = DefaultParameterPrism.getValue(memberValues, defaults, name, clazz);
if(result == null) valid = false;
return result;
}
private static @Nullable AnnotationMirror getMirror(String fqn, Element target) {
for (AnnotationMirror m :target.getAnnotationMirrors()) {
CharSequence mfqn = ((TypeElement)m.getAnnotationType().asElement()).getQualifiedName();
if(fqn.contentEquals(mfqn)) return m;
}
return null;
}
private static @Nullable T getValue(
Map memberValues,
Map defaults,
String name, Class clazz) {
AnnotationValue av = memberValues.get(name);
if(av == null) av = defaults.get(name);
if(av == null) {
return null;
}
if(clazz.isInstance(av.getValue())) return clazz.cast(av.getValue());
return null;
}
private static T requireMember(@Nullable T t) {
if (t == null) {
throw new java.util.NoSuchElementException("prism is invalid");
}
return t;
}
}