Stereotype Helper

Helps libraries to support stereotypes, so their users can encapsulate the libraries' annotations into their own, allowing to reuse them.

License

License

GroupId

GroupId

com.github.t1
ArtifactId

ArtifactId

stereotype-helper
Last Version

Last Version

1.0.8
Release Date

Release Date

Type

Type

jar
Description

Description

Stereotype Helper
Helps libraries to support stereotypes, so their users can encapsulate the libraries' annotations into their own, allowing to reuse them.
Project URL

Project URL

https://github.com/t1/stereotype-helper
Source Code Management

Source Code Management

https://github.com/t1/stereotype-helper.git

Download stereotype-helper

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.t1/stereotype-helper/ -->
<dependency>
    <groupId>com.github.t1</groupId>
    <artifactId>stereotype-helper</artifactId>
    <version>1.0.8</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.t1/stereotype-helper/
implementation 'com.github.t1:stereotype-helper:1.0.8'
// https://jarcasting.com/artifacts/com.github.t1/stereotype-helper/
implementation ("com.github.t1:stereotype-helper:1.0.8")
'com.github.t1:stereotype-helper:jar:1.0.8'
<dependency org="com.github.t1" name="stereotype-helper" rev="1.0.8">
  <artifact name="stereotype-helper" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.t1', module='stereotype-helper', version='1.0.8')
)
libraryDependencies += "com.github.t1" % "stereotype-helper" % "1.0.8"
[com.github.t1/stereotype-helper "1.0.8"]

Dependencies

provided (2)

Group / Artifact Type Version
javax.enterprise : cdi-api Optional jar 2.0.SP1
org.slf4j : slf4j-api jar 1.7.28

test (4)

Group / Artifact Type Version
junit : junit jar 4.13.1
org.assertj : assertj-core jar 3.13.2
ch.qos.logback : logback-classic jar 1.2.3
javax.annotation : javax.annotation-api jar 1.3.2

Project Modules

There are no modules declared in this project.

OBSOLETE: move to https://github.com/t1/power-annotations

About Build Status

Helps libraries with using annotations, supporting defaulting (e.g. from class to field) and stereotypes, so their users can encapsulate the libraries' annotations into their own, allowing to abstract and reuse them.

Similar to David Blevins' MetaTypes but this one can propagate stereotype properties and more. And this one uses the standard CDI @Stereotype annotation and assumes that you have can change the annotations you want to check (making things much easier).

The main entry point is the Annotations class.

Tutorial

Setup

Add a dependency:

<dependency>
    <groupId>com.github.t1</groupId>
    <artifactId>stereotype-helper</artifactId>
    <version>${latestVersion}</version>
</dependency>

Where latestVersion is Download (you can also download it from there).

The Basics: Reflecting on Annotations

Say you have an annotated field:

class Target {
    @FieldAnnotation
    public String field;
}

Without stereotype-helper, your code to check the presence of the annotation would look like this:

Field field = Target.class.getDeclaredField("field");
boolean present = field.isAnnotationPresent(FieldAnnotation.class);

With stereotype-helper, you'd use the Annotations class, instead:

Field field = Target.class.getDeclaredField("field");
boolean present = Annotations.on(field).isAnnotationPresent(FieldAnnotation.class);

There's a shortcut for those two lines:

boolean present = Annotations.onField(Target.class, "field")
    .isAnnotationPresent(FieldAnnotation.class);

Annotations has corresponding methods for methods and classes. They all return the standard Java java.lang.reflect.AnnotatedElement objects, so the syntax of using them stays exactly the same, only the entry point is different.

No big deal... so far.

Resolving Stereotypes

Stereotypes are a part of CDI to group annotations into reusable roles. But they mostly work only for CDI and Java EE annotations, as only few other frameworks know how to resolve stereotypes to the annotations they group. stereotype-helper does this for your framework (or library or wherever you want to react to the annotations)... as you tell from it's name.

First let's define a stereotype:

@Transactional
@MyAnnotation
@Stereotype
@Target(Method)
@Retention(RUNTIME)
public @interface Action {}

@Transactional is a Java EE annotation; @MethodAnnotation is the annotation we'd like to handle in our own framework. The other annotations define it as a stereotype.

When you use this stereotype like this:

class Type {
    @Action
    public void myMethod() {
        ...
    }
}

... then this should be true:

Annotations.onMethod(Type.class, "myMethod").isAnnotationPresent(MyAnnotation.class);

I.e. the annotations on the stereotype show up as if they where directly annotated at the target (method in this case).

Note that this resolution is recursive, i.e. it works also for stereotypes that are annotated with other stereotypes.

Stereotype Property Propagation

Say you have an annotation with a property like this:

public @interface Color {
    public String value() default "none";
}

... and a stereotype like this:

@Color("red")
@Stereotype
public @interface Red {
    public String value();
}

... then calling ...getAnnotation(Color.class).value() on something annotated as @Red will return red (which is generally not the case for stereotypes in CDI). Even more important, an annotation @Red("strawberry") would turn out as strawberry, i.e. the property is propagated from the stereotype to the annotation. One stereotype property can also be propagated to multiple annotations.

For propagation to work, the name as well as the type of the property must match. Alternatively you can explicitly configure it with PropagetTo, specifying the target types and property names.

Defaulting Annotations

Annotations on a class are effective for all methods and fields within that class, but can be overriden.

Annotations on a package are effective for all classes, methods, and fields within that package, but can be overriden.

Annotation Inheritance From Interfaces

In standard Java, classes inherit the annotations of their super class if the annotation itself is annotated as @Inherited. stereotype-helper does that for all interfaces implemented, too.

Versions

Version
1.0.8