The EsfingeMETADATA is an extensible framework for metadata validation, which aims to simplify and mainly assist the development of frameworks based on metadata. In addition, it can also be used in applications based on custom annotations.
commons-beanutils-1.9.2.jar
commons-collections-3.2.2.jar
commons-logging-1.2.jar
To find the annotations use the methodAnnotationFinder.findAnnotation
, this will return a list of Annotations.
List<Annotation> annotationList =AnnotationFinder.findAnnotation(container.getClass(), ContainerFor.class);
This annotation is used by validation annotations to identify which records must be validated by EsfingeMETADATA.
This meta-annotation is used by validation annotations to specify which attributes of the notes must be validated by EsfingeMETADATA.
This meta-annotation of configuration indicates that the retrieval of the annotation to be validated can be searched in the element that involves (levels above) the object informed as parameter, until reaching the extreme point of the search, in which there is no more where to look.
To run the validator metadata must perform the following steps:
import net.sf.esfinge.metadata.AnnotationValidationException
to call the EsfingeMetadata validation exceptions: import net.sf.esfinge.metadata.validate.MetadataValidator
, to declare that you will use EsfingeMetadata to validate your code: MetadataValidator.validateMetadataOn(Class<?>);
to search validations notes the EsfingeMetadata where the Class<?>
is the class that you want to validate: Example:
In order to validate the metadata, an annotation must first be created, in this example I am using the quantity with the annotation @unique
, and the annotations @SearchOnEnclosingElements
and @SearchInsideAnnotations
are to go through the annotation internally:
@SearchOnEnclosingElements
@SearchInsideAnnotations
@Target({ElementType.METHOD, ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PointsToUser {
@Unique
int quantity();
String name();
}
Class containing annotation to be validated by metadata validator:
public class Classe{
@PointsToUser(name="ponto", quantity=10)
public void registrar(){
}
}
Para validar o as anotações é necessário usar o método MetadataValidator.validateMetadataOn(Classe.class), se as anotações estiverem com alguma inconsistência vai ser executado a exceção AnnotationValidationException:
import net.sf.esfinge.metadata.AnnotationValidationException;
import net.sf.esfinge.metadata.validate.MetadataValidator;
public class ExemploMetadata {
public static void main(String[] args)
{
try {
MetadataValidator.validateMetadataOn
(Classe.class);
} catch
(AnnotationValidationException e) {
e.printStackTrace();
}
}
}
This annotation checks whether the method of a particular annotation is unique to a particular interface. That is, two methods of the same annotation can not be annotated with this type of annotation.
Example:
@SearchOnEnclosingElements
@SearchInsideAnnotations
@Target({ElementType.METHOD, ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PointsToUser {
@Unique
int quantity();
String name();
}
This meta-annotation checks whether a given attribute value is not null / empty for a particular annotation.
Example:
@SearchOnEnclosingElements
@SearchInsideAnnotations
@Target({ElementType.METHOD, ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PointsToUser {
int quantity();
@NotNull
String name();
}
This meta-annotation checks whether a given attribute value is not null / empty for a particular annotation. The validator defines the following attribute: value (): The minimum value of the annotation attribute it refers to.
Example:
@SearchOnEnclosingElements
@SearchInsideAnnotations
@Target({ElementType.METHOD, ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PointsToUser {
@MinValue(value=0)
int quantity();
String name();
}
This validator indicates that the attribute value of an annotation must be less than or equal to the value specified by the meta-annotation in question. The validator defines the following attribute: value (): The maximum value of the annotation attribute to which it refers.
Example:
@SearchOnEnclosingElements
@SearchInsideAnnotations
@Target({ElementType.METHOD, ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PointsToUser {
@MaxValue(value=10)
int quantity();
String name();
}
This validator indicates that the value of the attribute of an annotation must refer (be equal) to the value of the attribute of another annotation somewhere in the program. The validator defines the following attributes:
annotation()
:
Target annotation to which the current attribute refers. attributeValue()
:The value of the attribute of the target annotation to which the current attribute refers.
This validator states that if a code element is annotated with the current annotation, then it will prohibit the use of another informed annotation. This validator is defined by a single value()
attribute that tells the annotated class to be prohibited.
This validator is the opposite of @Prohibits
. It requires that the current meta-annotation should occur on elements that contain the annotation reported in value()
.
This annotation indicates that the field using annotated annotation must have the final
modifier.
Example:
@FinalFieldOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithFinalFieldOnly { }
This annotation indicates that the field using annotated annotation must have the static
modifier.
Example:
@StaticFieldOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithStaticFieldOnly { }
This annotation indicates that the field using annotated annotation must have the transient
modifier.
Example:
@TransientFieldOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithTransientFieldOnly { }
This annotation indicates that the field using annotated annotation must have the volatile
modifier.
Example:
@VolatileFieldOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithVolatileFieldOnly { }
This annotation indicates that the field uses the annotation annotated may NOT have the modifier static
.
Example:
@InstanceFieldOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithInstanceFieldOnly { }
This annotation indicates that the field that uses the annotated annotation may NOT have the visibility passed in the itCannotHaveThisVisibility
parameter.
Example:
@FieldVisibilityForbidden(itCannotHaveThisVisibility = "public") @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithFieldVisibilityForbidden { }
This annotation indicates that the field that uses the annotated annotation needs have the visibility passed in the itNeedsToHaveThisVisibility
parameter.
Example:
@FieldVisibilityRequired(itNeedsToHaveThisVisibility = "private") @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithFieldVisibilityRequired { }
This annotation indicates that the field that uses the annotated annotation needs have a type passed in the listValidTypes
parameter.
Example:
@ValidFieldTypes(listValidTypes = {String.class, List.class, int.class}) @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithValidFieldTypes { }
This annotation indicates that the method using annotated annotation must have the final
modifier.
Example:
@FinalMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithFinalMethodOnly { }
This annotation indicates that the method using annotated annotation must have the static
modifier.
Example:
@StaticMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithStaticMethodOnly { }
This annotation indicates that the method using annotated annotation must have the synchronized
modifier.
Example:
@SynchronizedMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithSynchronizedMethodOnly { }
This annotation indicates that the method using annotated annotation must have the strictfp
modifier.
Example:
@StrictfpMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithStrictfpMethodOnly { }
This annotation indicates that the method uses the annotation annotated may NOT have the modifier static
.
Example:
@InstanceMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithInstanceMethodOnly { }
This annotation indicates that the method that uses the annotated annotation may NOT have the visibility passed in the itCannotHaveThisVisibility
parameter.
Example:
@MethodVisibilityForbidden(itCannotHaveThisVisibility = "private") @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithMethodVisibilityForbidden { }
This annotation indicates that the method that uses the annotated annotation needs have the visibility passed in the itNeedsToHaveThisVisibility
parameter.
Example:
@MethodVisibilityRequired(itNeedsToHaveThisVisibility = "protected") @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithMethodVisibilityRequired { }
This annotation indicates that the method using the annotated annotation must have a method name according to the regular expression passed in the parameter regexNamingConvention
.
Example:
@MethodNamingConvention(regexNamingConvencion = "^get") @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithMethodNamingConvention { }
This annotation indicates that the method using annotated annotation can NOT have parameters.
Example:
@NoParametersMethodOnly @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithNoParametersMethodOnly { }
This annotation indicates that the method that uses the annotated annotation needs number of parameters passed in the numberOfParameters
parameter.
Example:
@ValidNumberOfParameters(numberOfParameters = 2) @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithValidNumberOfParameters { }
This annotation indicates that the method using the annotated annotation needs to have the parameters corresponding to what was passed in the validParameters
parameter, where valid parameters are indicated by the @Parameters
In the parameters
parameter.
Example:
@ValidMethodParameterTypes( validParameters = { @Parameters( parameters = {String.class, Integer.class} ), @Parameters( parameters = {String.class, int.class} ) } ) @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithValidMethodParameterTypes { }
This annotation indicates that the method that uses the annotated annotation CAN NOT have return passed in invalidTypesToReturn
parameter.
Example:
@ForbiddenMethodReturn(invalidTypesToReturn = {void.class, float.class}) @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithForbiddenMethodReturn { }
This annotation indicates that the method that uses the annotated annotation needs have return passed in validTypesToReturn
parameter.
Example:
@ValidMethodReturn(validTypesToReturn = {int.class, Integer.class}) @Retention(RetentionPolicy.RUNTIME) public @interface OneAnnotationWithValidMethodReturn { }
To create an extension for the metadata validator you must:
Create annotated annotation with:@ToValidateProperty()
Example:
@ToValidateProperty(validationClass = UniqueAnnotationValidator.class) @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Unique { }
Implement the AnnotationPropertyValidator, it has this structure:
public interface AnnotationPropertyValidator { public void initialize(Annotation self); public void validate(Annotation annotationOnElement, AnnotatedElement annotatedWithMainAnnotation, Method annotatedWithValidation, Object annotationPropertyValue) throws AnnotationValidationException; }
Where the initialize()
method is responsible for initializing the validation class and validate()
is responsible for validation;
Import static method: import static net.sf.esfinge.metadata.AnnotationReader.readingAnnotationsTo;
Container container = readingAnnotationsTo(Dominio.class, Container.class);
Where Domain.class is the class that will be captured the information and the Container.class is the class that will be stored the notes for future use.
Example: At first we created the target class of the metadata reader.
@Entidade @Tabela(nome="dominio") public class Dominio { private String nomeField; @FieldLista private int fieldTrue; public void entidadeFalse(){} @Proces public void entidadeTrue(){} }
Next we create a container with the metadata read annotations we want.
In this case, I'm wanting to know class information, such as the name, if it contains the annotated class.
@ContainerFor(vaule = ContainerTarget.CLASS) public class Container { @ContainsAnnotation(Entidade.class) private boolean entidade; @ElementName private String nomeClasse; @ReflectionReference private Class<?> classValue; @AnnotationProperty(annotation = Tabela.class, property ="nome") private String nomeTabela; @ProcessMethods private List<MethodContainer> listaMethod; @ProcessFields private List<FieldContainer> listaField; //métodos gets e sets omitidos }
In the case of method and field annotations, you must create a container with the @ContainerFor annotation for METHODS or FIELDS. Exemplo for METHOD:
@ContainerFor(vaule = ContainerTarget.METHODS) public class MethodContainer { @ContainsAnnotation(Proces.class) private boolean toProcess; @ElementName public String metodo; }
@ContainsAnnotation
This Fields annotation checks to see if the selected annotation exists on the target element. It contains only the value () method that returns if the selected annotation exists, this annotation should be used in boolean primitive types or Boolean type classes.
@AnnotationProperty
This annotation checks if there is an annotation annotated in the target class, and also verifies if there is a property with a name described.
@ElementName
This field annotation takes the name of the element that has been annotated and passes to the container field.
@ReflectionReference
This field annotation takes the class of the element that has been annotated and passes to the field that was annotated with this element.
@ProcessMethods
This annotation takes the information from the methods, and places it in a container with the Methods information, it must be stored in the List, Set, Map container with information about the Methods.
@ProcessFields
This annotation takes Fields information, and places it in a container with Fields information, it must be stored in the List, Set, Map of Containers for the fields.
@AllMethodsWith
This annotation takes the information from the Methods, and places it in a container with the Methods information, it must be stored in the List, Set, Map container with information about the methods. It contains only the value () method and only takes the Methods with that annotation defined in it.
@AllFieldsWith
This annotation takes Fields information, and places it in a container with Fields information, it must be stored in the List, Set, Map of Containers for the fields.
To create an extension for the Metadata Reader you must:
Create annotation with: @AnnotationReadingConfig()
This annotation will tell which annotation is being passed;
Placing the @ValidFieldType()
annotation, this annotation tells what types or classes annotations will be annotated. Example:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@AnnotationReadingConfig(AllFieldsWithReadingProcessor.class)
@ValidFieldType({List.class, Set.class,Map.class})
public @interface AllFieldsWith {
Class<? extends Annotation> value();
}
- Implement the AnnotationReadingProcessor
interface, it has this structure:
public interface AnnotationReadingProcessor {
void initAnnotation(Annotation an, Field field) throws AnnotationValidationException;
void read(AnnotatedElement classWithMetadata, Object container, ContainerTarget enumStr) throws AnnotationReadingException;
}
Where the init Annotation ()
function is responsible for initializing the validation class and read()
is responsible for reading the annotations:
Supported by