package org.springframework.roo.classpath.details; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.Validate; import org.springframework.roo.classpath.details.annotations.AnnotatedJavaType; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.itd.MemberHoldingTypeDetailsMetadataItem; import org.springframework.roo.classpath.scanner.MemberDetails; import org.springframework.roo.model.CustomData; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; /** * Utility methods for finding members in {@link MemberHoldingTypeDetails} * instances. * * @author Ben Alex * @author Stefan Schmidt * @author Andrew Swan * @author Juan Carlos GarcĂ­a * @since 1.0 */ public final class MemberFindingUtils { /** * Locates the metadata for an annotation of the specified type from within * the given list. * * @param annotations the set of annotations to search (may be * <code>null</code>) * @param annotationType the annotation to locate (may be <code>null</code>) * @return the annotation, or <code>null</code> if not found */ public static AnnotationMetadata getAnnotationOfType( final List<? extends AnnotationMetadata> annotations, final JavaType annotationType) { if (annotations == null) { return null; } for (final AnnotationMetadata annotation : annotations) { if (annotation.getAnnotationType().equals(annotationType)) { return annotation; } } return null; } /** * Returns the metadata for the annotation of the given type from within the * given metadata * * @param metadata the metadata to search; can be <code>null</code> * @param annotationType the type of annotation for which to return the * metadata; can be <code>null</code> * @return <code>null</code> if not found * @since 1.2.0 */ public static AnnotationMetadata getAnnotationOfType( final MemberHoldingTypeDetailsMetadataItem<?> metadata, final JavaType annotationType) { if (metadata == null || metadata.getMemberHoldingTypeDetails() == null) { return null; } return getAnnotationOfType(metadata.getMemberHoldingTypeDetails().getAnnotations(), annotationType); } /** * Searches all {@link MemberDetails} and returns all constructors. * * @param memberDetails the {@link MemberDetails} to search (required) * @return zero or more constructors (never null) * @deprecated use {@link MemberDetails#getConstructors()} instead */ @Deprecated public static List<ConstructorMetadata> getConstructors(final MemberDetails memberDetails) { return memberDetails.getConstructors(); } /** * Locates the specified constructor. * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search (required) * @param parameters to locate (can be null if there are no parameters) * @return the constructor, or null if not found * @deprecated use * {@link MemberHoldingTypeDetails#getDeclaredConstructor(List)} * instead */ @Deprecated public static ConstructorMetadata getDeclaredConstructor( final MemberHoldingTypeDetails memberHoldingTypeDetails, final List<JavaType> parameters) { return memberHoldingTypeDetails.getDeclaredConstructor(parameters); } /** * Locates the specified field of the given {@link MemberHoldingTypeDetails} * . * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search (required) * @param fieldName to locate (required) * @return the field, or null if not found * @deprecated call * {@link MemberHoldingTypeDetails#getDeclaredField(JavaSymbolName)} * instead */ @Deprecated public static FieldMetadata getDeclaredField( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName fieldName) { return memberHoldingTypeDetails.getDeclaredField(fieldName); } /** * Locates an inner type with the specified name. * * @param MemberDetails to search (required) * @param typeName to locate (required) * @deprecated use * {@link MemberHoldingTypeDetails#getDeclaredInnerType(JavaType)} * instead */ @Deprecated public static ClassOrInterfaceTypeDetails getDeclaredInnerType( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaType typeName) { return memberHoldingTypeDetails.getDeclaredInnerType(typeName); } /** * Locates a method on the specified {@link MemberHoldingTypeDetails} based * on the method name. * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search; can be <code>null</code> * @param methodName to locate; can be <code>null</code> * @return the method, or <code>null</code> if the given name was * <code>null</code> or it was simply not found */ public static MethodMetadata getDeclaredMethod( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName methodName) { if (memberHoldingTypeDetails == null) { return null; } for (final MethodMetadata method : memberHoldingTypeDetails.getDeclaredMethods()) { if (method.getMethodName().equals(methodName)) { return method; } } return null; } /** * Locates all methods on the specified {@link MemberHoldingTypeDetails} based * on the method name. * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search; can be <code>null</code> * @param methodName to locate; can be <code>null</code> * @return the list of methods, or <code>null</code> if the given name was * <code>null</code> or it was simply not found */ public static List<MethodMetadata> getDeclaredMethods( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName methodName) { if (memberHoldingTypeDetails == null) { return null; } List<MethodMetadata> methods = new ArrayList<MethodMetadata>(); for (final MethodMetadata method : memberHoldingTypeDetails.getDeclaredMethods()) { if (method.getMethodName().equals(methodName)) { methods.add(method); } } if (!methods.isEmpty()) { return methods; } return null; } /** * Locates the specified method. * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search; can be <code>null</code> * @param methodName to locate; can be <code>null</code> * @param parameters to locate (can be null if there are no parameters) * @return the method, or <code>null</code> if the given name was * <code>null</code> or it was simply not found */ public static MethodMetadata getDeclaredMethod( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName methodName, List<JavaType> parameters) { if (memberHoldingTypeDetails == null) { return null; } if (parameters == null) { parameters = new ArrayList<JavaType>(); } for (final MethodMetadata method : memberHoldingTypeDetails.getDeclaredMethods()) { if (method.getMethodName().equals(methodName)) { final List<JavaType> parameterTypes = AnnotatedJavaType.convertFromAnnotatedJavaTypes(method.getParameterTypes()); if (parameterTypes.equals(parameters)) { return method; } } } return null; } /** * Locates the specified type-level annotation. * * @param builder the {@link MemberHoldingTypeDetails} to search (required) * @param type to locate (required) * @return the annotation, or null if not found * @deprecated use * {@link AbstractIdentifiableAnnotatedJavaStructureBuilder#getDeclaredTypeAnnotation(JavaType)} * instead */ @Deprecated public static AnnotationMetadataBuilder getDeclaredTypeAnnotation( final AbstractIdentifiableAnnotatedJavaStructureBuilder<? extends IdentifiableAnnotatedJavaStructure> builder, final JavaType type) { return builder.getDeclaredTypeAnnotation(type); } /** * Locates the specified type-level annotation. * * @param memberHoldingTypeDetails the {@link MemberHoldingTypeDetails} to * search (required) * @param type to locate (required) * @return the annotation, or null if not found * @deprecated use * {@link IdentifiableAnnotatedJavaStructure#getAnnotation(JavaType)} * instead */ @Deprecated public static AnnotationMetadata getDeclaredTypeAnnotation( final IdentifiableAnnotatedJavaStructure memberHoldingTypeDetails, final JavaType type) { return memberHoldingTypeDetails.getAnnotation(type); } /** * Locates the specified type-level annotation. * * @param memberDetails the {@link MemberDetails} to search (required) * @param type to locate (required) * @return the annotation, or null if not found * @deprecated use {@link MemberDetails#getAnnotation(JavaType)} instead */ @Deprecated public static AnnotationMetadata getDeclaredTypeAnnotation(final MemberDetails memberDetails, final JavaType type) { return memberDetails.getAnnotation(type); } /** * Searches up the inheritance hierarchy until the first field with the * specified name is located. * * @param memberHoldingTypeDetails to search (required) * @param fieldName to locate (required) * @return the field, or null if not found * @deprecated use {@link MemberHoldingTypeDetails#getField(JavaSymbolName)} * instead */ @Deprecated public static FieldMetadata getField(final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName fieldName) { return memberHoldingTypeDetails.getField(fieldName); } /** * Searches all {@link MemberDetails} and returns all fields. * * @param memberDetails the {@link MemberDetails} to search (required) * @return zero or more fields (never null) * @deprecated use {@link MemberDetails#getFields()} instead */ @Deprecated public static List<FieldMetadata> getFields(final MemberDetails memberDetails) { return memberDetails.getFields(); } /** * Searches up the inheritance hierarchy and locates all declared fields * which are annotated with the specified annotation. * * @param memberHoldingTypeDetails to search (required) * @param annotation to locate (required) * @return all the located fields (never null, but may be empty) * @deprecated use * {@link MemberHoldingTypeDetails#getFieldsWithAnnotation(JavaType)} * instead */ @Deprecated public static List<FieldMetadata> getFieldsWithAnnotation( final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaType annotation) { return memberHoldingTypeDetails.getFieldsWithAnnotation(annotation); } /** * Returns all fields within the given {@link MemberDetails} that contain * the given {@link CustomData} tag. * * @param memberDetails the {@link MemberDetails} to search (can be * <code>null</code>) * @param tagKey the {@link CustomData} key to search for * @return zero or more fields (never <code>null</code>) */ public static List<FieldMetadata> getFieldsWithTag(final MemberDetails memberDetails, final Object tagKey) { Validate.notNull(tagKey, "Custom data key required"); final List<FieldMetadata> fields = new ArrayList<FieldMetadata>(); if (memberDetails != null) { for (final MemberHoldingTypeDetails memberHoldingTypeDetails : memberDetails.getDetails()) { for (final FieldMetadata field : memberHoldingTypeDetails.getDeclaredFields()) { if (field.getCustomData().keySet().contains(tagKey)) { fields.add(field); } } } } return fields; } /** * Returns the first of the given types of annotation on the given class or * interface * * @param cid the class or interface to check (can be <code>null</code>) * @param annotationTypes the types of annotation to look for, in order (can * be <code>null</code>) * @return <code>null</code> if the given type or array of annotations is * <code>null</code>, or none were found */ public static AnnotationMetadata getFirstAnnotation(final ClassOrInterfaceTypeDetails cid, final JavaType... annotationTypes) { if (cid != null && annotationTypes != null) { for (final JavaType annotationType : annotationTypes) { final AnnotationMetadata annotation = MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), annotationType); if (annotation != null) { return annotation; } } } return null; } /** * Searches all {@link MemberDetails} and returns all * {@link MemberHoldingTypeDetails} which contains a given * {@link CustomData} tag. * * @param memberDetails the {@link MemberDetails} to search (can be * <code>null</code>) * @param tagKey the {@link CustomData} key to search for (required) * @return zero or more {@link MemberHoldingTypeDetails} (never null) */ public static List<MemberHoldingTypeDetails> getMemberHoldingTypeDetailsWithTag( final MemberDetails memberDetails, final Object tagKey) { Validate.notNull(tagKey, "Custom data tag required"); final List<MemberHoldingTypeDetails> result = new ArrayList<MemberHoldingTypeDetails>(); if (memberDetails != null) { for (final MemberHoldingTypeDetails memberHoldingTypeDetails : memberDetails.getDetails()) { if (memberHoldingTypeDetails.getCustomData().keySet().contains(tagKey)) { result.add(memberHoldingTypeDetails); } } } return result; } /** * Locates a method with the name presented. Searches all * {@link MemberDetails} until the first such method is located or none can * be found. * * @param memberDetails the {@link MemberDetails} to search (required) * @param methodName the method name to locate (can be <code>null</code>) * @return the first located method, or <code>null</code> if the method name * is <code>null</code> or such a method cannot be found * @deprecated use {@link MemberDetails#getMethod(JavaSymbolName)} instead */ @Deprecated public static MethodMetadata getMethod(final MemberDetails memberDetails, final JavaSymbolName methodName) { return memberDetails.getMethod(methodName); } /** * Locates a method with the name and parameter signature presented. * Searches all {@link MemberDetails} until the first such method is located * or none can be found. * * @param memberDetails the {@link MemberDetails} to search (required) * @param methodName the method name to locate (can be <code>null</code>) * @param parameters the method parameter signature to locate (can be null * if no parameters are required) * @return the first located method, or <code>null</code> if the method name * is <code>null</code> or such a method cannot be found * @deprecated use {@link MemberDetails#getMethod(JavaSymbolName, List)} * instead */ @Deprecated public static MethodMetadata getMethod(final MemberDetails memberDetails, final JavaSymbolName methodName, final List<JavaType> parameters) { return memberDetails.getMethod(methodName, parameters); } /** * Locates a method with the name and parameter signature presented that is * not declared by the presented MID. * * @param memberDetails the {@link MemberDetails} to search (required) * @param methodName the method name to locate (can be <code>null</code>) * @param parameters the method parameter signature to locate (can be null * if no parameters are required) * @param excludingMid the MID that a found method cannot be declared by * @return the first located method, or <code>null</code> if the method name * is <code>null</code> or such a method cannot be found * @deprecated use * {@link MemberDetails#getMethod(JavaSymbolName, List, String)} * instead */ @Deprecated public static MethodMetadata getMethod(final MemberDetails memberDetails, final JavaSymbolName methodName, final List<JavaType> parameters, final String excludingMid) { return memberDetails.getMethod(methodName, parameters, excludingMid); } /** * Convenience method which converts a String method name to a * {@link JavaSymbolName} for use by the standard * {@link #getMethod(MemberDetails, org.springframework.roo.model.JavaSymbolName)} * . * * @param memberHoldingTypeDetails to search (required) * @param methodName to locate (required) * @return the method, or null if not found */ public static MethodMetadata getMethod(final MemberDetails memberDetails, final String methodName) { Validate.notNull(methodName, "Method name required"); return memberDetails.getMethod(new JavaSymbolName(methodName)); } /** * Searches up the inheritance hierarchy until the first method with the * specified name is located, method parameters are not taken into account. * * @param memberHoldingTypeDetails to search (required) * @param methodName to locate (required) * @return the method, or null if not found * @deprecated use * {@link MemberHoldingTypeDetails#getMethod(JavaSymbolName)} * instead */ @Deprecated public static MethodMetadata getMethod(final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName methodName) { return memberHoldingTypeDetails.getMethod(methodName); } /** * Searches up the inheritance hierarchy until the first method with the * specified name and parameters is located. * * @param memberHoldingTypeDetails to search (required) * @param methodName to locate (required) * @param parameters to locate (can be null if there are no parameters) * @return the method, or null if not found * @deprecated use * {@link MemberHoldingTypeDetails#getMethod(JavaSymbolName, List)} * instead */ @Deprecated public static MethodMetadata getMethod(final MemberHoldingTypeDetails memberHoldingTypeDetails, final JavaSymbolName methodName, final List<JavaType> parameters) { return memberHoldingTypeDetails.getMethod(methodName, parameters); } /** * Convenience method which converts a String method name to a * {@link JavaSymbolName} for use by the standard * {@link #getMethod(MemberHoldingTypeDetails, org.springframework.roo.model.JavaSymbolName)} * . * * @param memberHoldingTypeDetails to search (required) * @param methodName to locate (required) * @return the method, or null if not found */ public static MethodMetadata getMethod(final MemberHoldingTypeDetails memberHoldingTypeDetails, final String methodName) { return memberHoldingTypeDetails.getMethod(new JavaSymbolName(methodName)); } /** * Searches all {@link MemberDetails} and returns all methods. * * @param memberDetails the {@link MemberDetails} to search (required) * @return zero or more methods (never null) * @deprecated use {@link MemberDetails#getMethods()} instead */ @Deprecated public static List<MethodMetadata> getMethods(final MemberDetails memberDetails) { return memberDetails.getMethods(); } /** * Locates all methods on this class and its superclasses. * * @param memberHoldingTypeDetails to search (required) * @return zero or more methods (never null) * @deprecated use {@link MemberHoldingTypeDetails#getMethods()} instead */ @Deprecated public static List<MethodMetadata> getMethods( final MemberHoldingTypeDetails memberHoldingTypeDetails) { return memberHoldingTypeDetails.getMethods(); } /** * Searches all {@link MemberDetails} and returns all methods which contain * a given {@link CustomData} tag. * * @param memberDetails the {@link MemberDetails} to search (required) * @param tagKey the {@link CustomData} key to search for * @return zero or more methods (never null) * @deprecated use {@link MemberDetails#getMethodsWithTag(Object)} instead */ @Deprecated public static List<MethodMetadata> getMethodsWithTag(final MemberDetails memberDetails, final Object tagKey) { return memberDetails.getMethodsWithTag(tagKey); } /** * Determines the most concrete {@link MemberHoldingTypeDetails} in cases * where multiple matches are found for a given tag. * * @param memberDetails the {@link MemberDetails} to search (can be * <code>null</code>) * @param tag the {@link CustomData} key to search for (required) * @return the most concrete tagged type or null if not found */ public static MemberHoldingTypeDetails getMostConcreteMemberHoldingTypeDetailsWithTag( final MemberDetails memberDetails, final Object tag) { Validate.notNull(tag, "Custom data tag required"); final List<MemberHoldingTypeDetails> memberHoldingTypeDetailsList = getMemberHoldingTypeDetailsWithTag(memberDetails, tag); if (memberHoldingTypeDetailsList.isEmpty()) { return null; } return memberHoldingTypeDetailsList.get(memberHoldingTypeDetailsList.size() - 1); } /** * Determines the most concrete {@link MemberHoldingTypeDetails} in cases * where multiple matches are found for a given tag. * * @param memberDetails the {@link MemberDetails} to search (can be * <code>null</code>) * @param tagKey the {@link CustomData} key to search for (required) * @return the most concrete tagged method or <code>null</code> if not found */ public static MethodMetadata getMostConcreteMethodWithTag(final MemberDetails memberDetails, final Object tagKey) { if (memberDetails == null) { return null; } return memberDetails.getMostConcreteMethodWithTag(tagKey); } /** * Locates an annotation on this class and its superclasses. * * @param memberHoldingTypeDetails to search (required) * @param annotationType annotation to locate (required) * @return the annotation, or null if not found * @deprecated use * {@link IdentifiableAnnotatedJavaStructure#getTypeAnnotation(JavaType)} * instead */ @Deprecated public static AnnotationMetadata getTypeAnnotation( final IdentifiableAnnotatedJavaStructure memberHoldingTypeDetails, final JavaType annotationType) { return memberHoldingTypeDetails.getTypeAnnotation(annotationType); } /** * Constructor is private to prevent instantiation * * @since 1.2.0 */ private MemberFindingUtils() {} }