package org.springframework.roo.classpath.details.annotations.populator; import org.apache.commons.lang3.Validate; import org.springframework.roo.classpath.PhysicalTypeMetadata; import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails; import org.springframework.roo.classpath.details.MemberHoldingTypeDetails; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.itd.MemberHoldingTypeDetailsMetadataItem; import org.springframework.roo.model.JavaType; /** * Abstract class that provides a convenience parser and holder for annotation * values. Useful if an add-on needs to share annotation parsing outcomes * between its provider and metadata instances. * * @author Ben Alex * @since 1.0 */ public abstract class AbstractAnnotationValues { protected AnnotationMetadata annotationMetadata; /** * Indicates whether the class was able to be parsed at all (ie the metadata * was properly formed) */ protected boolean classParsed; protected ClassOrInterfaceTypeDetails governorTypeDetails; protected AbstractAnnotationValues(final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaType annotationType) { Validate.notNull(annotationType, "Annotation to locate is required"); if (memberHoldingTypeDetails instanceof ClassOrInterfaceTypeDetails) { classParsed = true; // We have reliable physical type details governorTypeDetails = (ClassOrInterfaceTypeDetails) memberHoldingTypeDetails; // Process values from the annotation, if present annotationMetadata = governorTypeDetails.getAnnotation(annotationType); } } /** * Convenience constructor that takes a {@link Class} for the annotation * type * * @param governorMetadata to parse (can be <code>null</code>) * @param annotationType the annotation class (required) */ protected AbstractAnnotationValues( final MemberHoldingTypeDetailsMetadataItem<?> governorMetadata, final Class<?> annotationType) { this(governorMetadata, new JavaType(annotationType)); } /** * Parses the governor's metadata for the requested annotation * {@link JavaType}. If found, makes the annotation available via the * {@link #annotationMetadata} field. Subclasses will then generally use * {@link AutoPopulationUtils#populate(Object, AnnotationMetadata)} to * complete the configuration of the subclass (we don't invoke * {@link AutoPopulationUtils} from this constructor because the subclass is * likely to have set default values for each field, and these will be * overwritten when the control flow returns to the subclass constructor). * <p> * If the {@link PhysicalTypeMetadata} cannot be parsed or does not * internally contain a {@link ClassOrInterfaceTypeDetails}, no attempt will * be made to populate the values. * * @param governorMetadata to parse (can be <code>null</code>) * @param annotationType to locate and parse (can be <code>null</code>) */ protected AbstractAnnotationValues( final MemberHoldingTypeDetailsMetadataItem<?> governorMetadata, final JavaType annotationType) { Validate.notNull(annotationType, "Annotation to locate is required"); if (governorMetadata != null) { final Object governorDetails = governorMetadata.getMemberHoldingTypeDetails(); if (governorDetails instanceof ClassOrInterfaceTypeDetails) { classParsed = true; // We have reliable physical type details governorTypeDetails = (ClassOrInterfaceTypeDetails) governorDetails; // Process values from the annotation, if present annotationMetadata = governorTypeDetails.getAnnotation(annotationType); } } } /** * Parses the governor's metadata for the requested annotation * {@link JavaType}. If found, makes the annotation available via the * {@link #annotationMetadata} field. Subclasses will then generally use * {@link AutoPopulationUtils#populate(Object, AnnotationMetadata)} to * complete the configuration of the subclass (we don't invoke * {@link AutoPopulationUtils} from this constructor because the subclass is * likely to have set default values for each field, and these will be * overwritten when the control flow returns to the subclass constructor). * <p> * If the {@link PhysicalTypeMetadata} cannot be parsed or does not * internally contain a {@link ClassOrInterfaceTypeDetails}, no attempt will * be made to populate the values. * * @param governorMetadata to parse (can be <code>null</code>) * @param annotationType to locate and parse (can be <code>null</code>) */ protected AbstractAnnotationValues(final ClassOrInterfaceTypeDetails governorDetails, final JavaType annotationType) { Validate.notNull(annotationType, "Annotation to locate is required"); if (governorDetails != null) { classParsed = true; // We have reliable physical type details governorTypeDetails = (ClassOrInterfaceTypeDetails) governorDetails; // Process values from the annotation, if present annotationMetadata = governorTypeDetails.getAnnotation(annotationType); } } /** * @return the type which declared the annotation (ie the governor; never * returns null) */ public ClassOrInterfaceTypeDetails getGovernorTypeDetails() { return governorTypeDetails; } public boolean isAnnotationFound() { return annotationMetadata != null; } public boolean isClassParsed() { return classParsed; } }