Class AnnotationBuilder<A extends Annotation>
- java.lang.Object
-
- org.perfectable.introspection.AnnotationBuilder<A>
-
- Type Parameters:
A
- annotation type to build
@Immutable public final class AnnotationBuilder<A extends Annotation> extends Object
Builder pattern for creating annotation type instances.Sometimes library methods require passing annotation instance, assuming that client will obtain it from reflection on some member or type. This is often poor design, but sometimes some API actually is defined by annotations rather than usual program structure.
In these cases, trying to call those methods, client has two straightforward options:
- Create token members or types with required annotation them and extract this annotation before call.
- Actually implement annotation interface, either by anonymous class place of call, or as a named somewhere near.
Both of those solutions are problematic. Beside introduction of unnecessary declaration, they also:
- If different annotation member values are needed, multiple synthetic annotation targets needs to be declared.
- Annotation interfaces as a rule should not be implemented, and static checkers will mark. Implemented
interface will often have repeated constructs, and should have
toString
,hashCode
andequals
implemented, but often it doesn't.
This class helps create instances of annotation type that are indistinguishable from ones extracted by reflection. These have same
toString
andhashCode
andequals
that works with native ones.If annotation has no members (is effectively a marker), it can be completely constructed by
marker(java.lang.Class<A>)
call.Otherwise annotation instance should be build starting with
of(java.lang.Class<A>)
, with zero or more calls towith(org.perfectable.introspection.AnnotationBuilder.MemberExtractor<A, X>, X)
and thenbuild()
. Every member of the annotation (i.e. annotation interface method) that doesn't have default value, needs to have value set, and this requirement is checked in thebuild()
method.Instances of this class are immutable, can be shared between threads and stored in global variables. Products of this builder are also immutable, as are all annotation instances.
Example of marker annotation creation:
Immutable immutableInstance = AnnotationBuilder.marker(Immutable.class);
Example of more complex annotation creation:
AnnotationBuilder<Tag> tagBuilder = AnnotationBuilder.of(Tag.class); Tag tag1 = tagBuilder.with(Tag::value, "one").build(); Tag tag2 = tagBuilder.with(Tag::value, "two").build(); Tags tags = AnnotationBuilder.of(Tags.class).with(Tags::value, new Tag[] { tag1, tag2 }).build();
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
AnnotationBuilder.MemberExtractor<A extends Annotation,X>
Functional reference interface which allows type-safe and refactor-safe extraction of members.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description A
build()
Creates annotation instance.static <A extends Annotation>
Amarker(Class<A> annotationType)
Creates instance of annotation with no members.static <A extends Annotation>
AnnotationBuilder<A>of(Class<A> annotationType)
Creates unconfigured builder for specified annotation type.<X> AnnotationBuilder<A>
with(AnnotationBuilder.MemberExtractor<A,X> member, X value)
Configures member of created annotation instances to have specified value.
-
-
-
Method Detail
-
marker
public static <A extends Annotation> A marker(Class<A> annotationType)
Creates instance of annotation with no members.If annotation have members, but all of them are default, this method will still
This method is pure - with the same arguments will produce equivalent results.
- Type Parameters:
A
- type of annotation to build- Parameters:
annotationType
- representation of type of annotation to build- Returns:
- Only annotation instance that can be created for this annotation.
- Throws:
IllegalArgumentException
- when provided class does not represent an annotation interfaceIllegalArgumentException
- when provided annotation type has any members
-
of
public static <A extends Annotation> AnnotationBuilder<A> of(Class<A> annotationType)
Creates unconfigured builder for specified annotation type.- Type Parameters:
A
- type of annotation to build- Parameters:
annotationType
- representation of type of annotation to build- Returns:
- Fresh, unconfigured builder
- Throws:
IllegalArgumentException
- when provided class does not represent an annotation interface
-
with
public <X> AnnotationBuilder<A> with(AnnotationBuilder.MemberExtractor<A,X> member, X value)
Configures member of created annotation instances to have specified value.Member is selected by client by providing method reference.
Builder will reject setting value for a member that has already value configured.
- Type Parameters:
X
- type of member- Parameters:
member
- reference to method which represents a configured membervalue
- value for specified member in annotation instance- Returns:
- new builder, with additional member configured
- Throws:
IllegalArgumentException
- when member is not a method reference to member of this builders annotation type or when value is not actually instance of member type
-
build
public A build()
Creates annotation instance.Performs member validation: each non-default member must have configured value.
- Returns:
- annotation instance with configured members
-
-