io.avaje.inject.generator.SingletonPrism Maven / Gradle / Ivy
package io.avaje.inject.generator;
import static java.util.stream.Collectors.*;
import java.util.stream.Stream;
import javax.lang.model.type.DeclaredType;
import java.util.Set;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Map;
import javax.annotation.processing.Generated;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.type.TypeMirror;
import java.util.HashMap;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
/** A Prism representing a {@link javax.inject.Singleton @Singleton} annotation. */
@Generated("avaje-prism-generator")
final class SingletonPrism {
public static final String PRISM_TYPE = "javax.inject.Singleton";
/**
* An instance of the Values inner class whose
* methods return the AnnotationValues used to build this prism.
* Primarily intended to support using Messager.
*/
final Values values;
/** Returns true if the mirror is an instance of {@link javax.inject.Singleton @Singleton} is present on the element, else false.
*
* @param mirror mirror.
* @return true if prism is present.
*/
static boolean isInstance(AnnotationMirror mirror) {
return getInstance(mirror) != null;
}
/** Returns true if {@link javax.inject.Singleton @Singleton} is present on the element, else false.
*
* @param element element.
* @return true if annotation is present on the element.
*/
static boolean isPresent(Element element) {
return getInstanceOn(element) != null;
}
/** Return a prism representing the {@link javax.inject.Singleton @Singleton} annotation present on the given element.
* similar to {@code element.getAnnotation(Singleton.class)} except that
* an instance of this class rather than an instance of {@link javax.inject.Singleton @Singleton}
* is returned.
*
* @param element element.
* @return prism on element or null if no annotation is found.
*/
static SingletonPrism getInstanceOn(Element element) {
final var mirror = getMirror(element);
if (mirror == null) return null;
return getInstance(mirror);
}
/** Return a Optional representing a nullable {@link javax.inject.Singleton @Singleton} annotation on the given element.
* similar to {@code element.getAnnotation(javax.inject.Singleton.class)} except that
* an Optional of this class rather than an instance of {@link javax.inject.Singleton}
* is returned.
*
* @param element element.
* @return prism optional for element.
*/
static Optional getOptionalOn(Element element) {
final var mirror = getMirror(element);
if (mirror == null) return Optional.empty();
return getOptional(mirror);
}
/** Return a list of prisms representing the {@link javax.inject.Singleton @Singleton} meta annotation on all the annotations on the given element.
* this method will recursively search all the annotations on the element.
*
* @param element element.
* @return list of prisms on the element's annotation.
*/
static List getAllOnMetaAnnotations(Element element) {
if (element == null || element.getAnnotationMirrors().isEmpty()) return List.of();
//use a hashset to keep track of seen annotations
return getAllOnMetaAnnotations(element, new HashSet<>()).collect(toList());
}
/** Recursively search annotation elements for prisms.
* Uses a set to keep track of known annotations to avoid repeats/recursive loop.
*
* @param element element.
* @param seen set that tracks seen elements.
* @return stream of prisms on the element's annotation.
*/
private static Stream getAllOnMetaAnnotations(Element element, Set seen) {
if (element == null || element.getAnnotationMirrors().isEmpty()) return Stream.of();
return element.getAnnotationMirrors().stream()
.map(AnnotationMirror::getAnnotationType)
//only search annotations
.filter(t -> seen.add(t.toString()))
.map(DeclaredType::asElement)
.flatMap(
e ->
Stream.concat(
getAllOnMetaAnnotations(e, seen),
getMirrors(element).map(SingletonPrism::getInstance)));
}
/** Return a prism of the {@link javax.inject.Singleton @Singleton} annotation from an annotation mirror.
*
* @param mirror mirror.
* @return prism for mirror or null if mirror is an incorrect type.
*/
static SingletonPrism getInstance(AnnotationMirror mirror) {
if (mirror == null || !PRISM_TYPE.equals(mirror.getAnnotationType().toString())) return null;
return new SingletonPrism(mirror);
}
/** Return an Optional representing a nullable {@link SingletonPrism @SingletonPrism} from an annotation mirror.
* similar to {@code e.getAnnotation(javax.inject.Singleton.class)} except that
* an Optional of this class rather than an instance of {@link javax.inject.Singleton @Singleton}
* is returned.
*
* @param mirror mirror.
* @return prism optional for mirror.
*/
static Optional getOptional(AnnotationMirror mirror) {
if (mirror == null || !PRISM_TYPE.equals(mirror.getAnnotationType().toString())) return Optional.empty();
return Optional.of(new SingletonPrism(mirror));
}
private SingletonPrism(AnnotationMirror mirror) {
for (final ExecutableElement key : mirror.getElementValues().keySet()) {
memberValues.put(key.getSimpleName().toString(), mirror.getElementValues().get(key));
}
for (final ExecutableElement member : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
defaults.put(member.getSimpleName().toString(), member.getDefaultValue());
}
this.values = new Values(memberValues);
this.mirror = mirror;
this.isValid = valid;
}
/**
* 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.
*/
final boolean isValid;
/**
* The underlying AnnotationMirror of the annotation
* represented by this Prism.
* Primarily intended to support using Messager.
*/
final AnnotationMirror mirror;
/**
* A class whose members correspond to those of {@link javax.inject.Singleton @Singleton}
* 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.
*/
static final class Values {
private final Map values;
private Values(Map values) {
this.values = values;
}
}
private final Map defaults = new HashMap(10);
private final Map memberValues = new HashMap(10);
private boolean valid = true;
private static AnnotationMirror getMirror(Element target) {
for (final var m : target.getAnnotationMirrors()) {
final CharSequence mfqn = ((TypeElement) m.getAnnotationType().asElement()).getQualifiedName();
if (PRISM_TYPE.contentEquals(mfqn)) return m;
}
return null;
}
private static Stream extends AnnotationMirror> getMirrors(Element target) {
return target.getAnnotationMirrors().stream()
.filter(
m -> PRISM_TYPE.contentEquals(((TypeElement) m.getAnnotationType().asElement()).getQualifiedName()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy