|
|
|
|
@ -114,7 +114,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -114,7 +114,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public String getString(String attributeName) { |
|
|
|
|
return doGet(attributeName, String.class); |
|
|
|
|
return getRequiredAttribute(attributeName, String.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -130,7 +130,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -130,7 +130,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public String[] getStringArray(String attributeName) { |
|
|
|
|
return doGet(attributeName, String[].class); |
|
|
|
|
return getRequiredAttribute(attributeName, String[].class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -157,32 +157,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -157,32 +157,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
*/ |
|
|
|
|
public String[] getAliasedStringArray(String attributeName, Class<? extends Annotation> annotationType, |
|
|
|
|
Object annotationSource) { |
|
|
|
|
|
|
|
|
|
Assert.hasText(attributeName, "attributeName must not be null or empty"); |
|
|
|
|
Assert.notNull(annotationType, "annotationType must not be null"); |
|
|
|
|
|
|
|
|
|
String[] attributeValue = getStringArrayWithoutNullCheck(attributeName); |
|
|
|
|
String aliasName = AnnotationUtils.getAttributeAliasMap(annotationType).get(attributeName); |
|
|
|
|
String[] aliasValue = getStringArrayWithoutNullCheck(aliasName); |
|
|
|
|
boolean attributeDeclared = !ObjectUtils.isEmpty(attributeValue); |
|
|
|
|
boolean aliasDeclared = !ObjectUtils.isEmpty(aliasValue); |
|
|
|
|
|
|
|
|
|
if (!ObjectUtils.nullSafeEquals(attributeValue, aliasValue) && attributeDeclared && aliasDeclared) { |
|
|
|
|
String elementName = (annotationSource == null ? "unknown element" : annotationSource.toString()); |
|
|
|
|
String msg = String.format("In annotation [%s] declared on [%s], " |
|
|
|
|
+ "attribute [%s] and its alias [%s] are present with values of [%s] and [%s], " |
|
|
|
|
+ "but only one is permitted.", this.displayName, elementName, attributeName, aliasName, |
|
|
|
|
ObjectUtils.nullSafeToString(attributeValue), ObjectUtils.nullSafeToString(aliasValue)); |
|
|
|
|
throw new AnnotationConfigurationException(msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!attributeDeclared) { |
|
|
|
|
attributeValue = aliasValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
assertAttributePresence(attributeName, aliasName, attributeValue); |
|
|
|
|
|
|
|
|
|
return attributeValue; |
|
|
|
|
return getRequiredArrayWithAttributeAlias(attributeName, annotationType, annotationSource, String[].class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -195,7 +170,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -195,7 +170,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public boolean getBoolean(String attributeName) { |
|
|
|
|
return doGet(attributeName, Boolean.class); |
|
|
|
|
return getRequiredAttribute(attributeName, Boolean.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -209,7 +184,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -209,7 +184,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public <N extends Number> N getNumber(String attributeName) { |
|
|
|
|
return (N) doGet(attributeName, Number.class); |
|
|
|
|
return (N) getRequiredAttribute(attributeName, Number.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -223,7 +198,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -223,7 +198,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public <E extends Enum<?>> E getEnum(String attributeName) { |
|
|
|
|
return (E) doGet(attributeName, Enum.class); |
|
|
|
|
return (E) getRequiredAttribute(attributeName, Enum.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -237,7 +212,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -237,7 +212,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public <T> Class<? extends T> getClass(String attributeName) { |
|
|
|
|
return doGet(attributeName, Class.class); |
|
|
|
|
return getRequiredAttribute(attributeName, Class.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -253,7 +228,34 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -253,7 +228,34 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public Class<?>[] getClassArray(String attributeName) { |
|
|
|
|
return doGet(attributeName, Class[].class); |
|
|
|
|
return getRequiredAttribute(attributeName, Class[].class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the value stored under the specified {@code attributeName} as an |
|
|
|
|
* array of classes, taking into account alias semantics defined via |
|
|
|
|
* {@link AliasFor @AliasFor}. |
|
|
|
|
* <p>If there is no value stored under the specified {@code attributeName} |
|
|
|
|
* but the attribute has an alias declared via {@code @AliasFor}, the |
|
|
|
|
* value of the alias will be returned. |
|
|
|
|
* |
|
|
|
|
* @param attributeName the name of the attribute to get; never |
|
|
|
|
* {@code null} or empty |
|
|
|
|
* @param annotationType the type of annotation represented by this |
|
|
|
|
* {@code AnnotationAttributes} instance; never {@code null} |
|
|
|
|
* @param annotationSource the source of the annotation represented by |
|
|
|
|
* this {@code AnnotationAttributes} (e.g., the {@link AnnotatedElement}); |
|
|
|
|
* or {@code null} if unknown |
|
|
|
|
* @return the array of classes |
|
|
|
|
* @throws IllegalArgumentException if the attribute and its alias do |
|
|
|
|
* not exist or are not of type {@code Class[]} |
|
|
|
|
* @throws AnnotationConfigurationException if the attribute and its |
|
|
|
|
* alias are both present with different non-empty values |
|
|
|
|
* @since 4.2 |
|
|
|
|
*/ |
|
|
|
|
public Class<?>[] getAliasedClassArray(String attributeName, Class<? extends Annotation> annotationType, |
|
|
|
|
Object annotationSource) { |
|
|
|
|
return getRequiredArrayWithAttributeAlias(attributeName, annotationType, annotationSource, Class[].class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -268,7 +270,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -268,7 +270,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public AnnotationAttributes getAnnotation(String attributeName) { |
|
|
|
|
return doGet(attributeName, AnnotationAttributes.class); |
|
|
|
|
return getRequiredAttribute(attributeName, AnnotationAttributes.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -283,7 +285,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -283,7 +285,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* @since 4.2 |
|
|
|
|
*/ |
|
|
|
|
public <A extends Annotation> A getAnnotation(String attributeName, Class<A> annotationType) { |
|
|
|
|
return doGet(attributeName, annotationType); |
|
|
|
|
return getRequiredAttribute(attributeName, annotationType); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -301,7 +303,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -301,7 +303,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
public AnnotationAttributes[] getAnnotationArray(String attributeName) { |
|
|
|
|
return doGet(attributeName, AnnotationAttributes[].class); |
|
|
|
|
return getRequiredAttribute(attributeName, AnnotationAttributes[].class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -321,7 +323,83 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -321,7 +323,83 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
public <A extends Annotation> A[] getAnnotationArray(String attributeName, Class<A> annotationType) { |
|
|
|
|
Object array = Array.newInstance(annotationType, 0); |
|
|
|
|
return (A[]) doGet(attributeName, array.getClass()); |
|
|
|
|
return (A[]) getRequiredAttribute(attributeName, array.getClass()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the value stored under the specified {@code attributeName} as an |
|
|
|
|
* array of the {@code expectedType}, taking into account alias semantics |
|
|
|
|
* defined via {@link AliasFor @AliasFor}. |
|
|
|
|
* <p>If there is no value stored under the specified {@code attributeName} |
|
|
|
|
* but the attribute has an alias declared via {@code @AliasFor}, the |
|
|
|
|
* value of the alias will be returned. |
|
|
|
|
* |
|
|
|
|
* @param attributeName the name of the attribute to get; never |
|
|
|
|
* {@code null} or empty |
|
|
|
|
* @param annotationType the type of annotation represented by this |
|
|
|
|
* {@code AnnotationAttributes} instance; never {@code null} |
|
|
|
|
* @param annotationSource the source of the annotation represented by |
|
|
|
|
* this {@code AnnotationAttributes} (e.g., the {@link AnnotatedElement}); |
|
|
|
|
* or {@code null} if unknown |
|
|
|
|
* @param expectedType the expected array type; never {@code null} |
|
|
|
|
* @return the array of values |
|
|
|
|
* @throws IllegalArgumentException if the attribute and its alias do |
|
|
|
|
* not exist or are not of the {@code expectedType}, or if the |
|
|
|
|
* {@code expectedType} is not an array |
|
|
|
|
* @throws AnnotationConfigurationException if the attribute and its |
|
|
|
|
* alias are both present with different non-empty values |
|
|
|
|
* @since 4.2 |
|
|
|
|
*/ |
|
|
|
|
private <T> T getRequiredArrayWithAttributeAlias(String attributeName, Class<? extends Annotation> annotationType, |
|
|
|
|
Object annotationSource, Class<T> expectedType) { |
|
|
|
|
|
|
|
|
|
Assert.hasText(attributeName, "attributeName must not be null or empty"); |
|
|
|
|
Assert.notNull(annotationType, "annotationType must not be null"); |
|
|
|
|
Assert.notNull(expectedType, "expectedType must not be null"); |
|
|
|
|
Assert.isTrue(expectedType.isArray(), "expectedType must be an array"); |
|
|
|
|
|
|
|
|
|
T attributeValue = getAttribute(attributeName, expectedType); |
|
|
|
|
String aliasName = AnnotationUtils.getAttributeAliasMap(annotationType).get(attributeName); |
|
|
|
|
T aliasValue = getAttribute(aliasName, expectedType); |
|
|
|
|
boolean attributeDeclared = !ObjectUtils.isEmpty((Object[]) attributeValue); |
|
|
|
|
boolean aliasDeclared = !ObjectUtils.isEmpty((Object[]) aliasValue); |
|
|
|
|
|
|
|
|
|
if (!ObjectUtils.nullSafeEquals(attributeValue, aliasValue) && attributeDeclared && aliasDeclared) { |
|
|
|
|
String elementName = (annotationSource == null ? "unknown element" : annotationSource.toString()); |
|
|
|
|
String msg = String.format("In annotation [%s] declared on [%s], " |
|
|
|
|
+ "attribute [%s] and its alias [%s] are present with values of [%s] and [%s], " |
|
|
|
|
+ "but only one is permitted.", this.displayName, elementName, attributeName, aliasName, |
|
|
|
|
ObjectUtils.nullSafeToString(attributeValue), ObjectUtils.nullSafeToString(aliasValue)); |
|
|
|
|
throw new AnnotationConfigurationException(msg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!attributeDeclared) { |
|
|
|
|
attributeValue = aliasValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
assertAttributePresence(attributeName, aliasName, attributeValue); |
|
|
|
|
|
|
|
|
|
return attributeValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the value stored under the specified {@code attributeName}, |
|
|
|
|
* ensuring that the value is of the {@code expectedType}. |
|
|
|
|
* @param attributeName the name of the attribute to get; never |
|
|
|
|
* {@code null} or empty |
|
|
|
|
* @param expectedType the expected type; never {@code null} |
|
|
|
|
* @return the value |
|
|
|
|
* @throws IllegalArgumentException if the attribute is not of the |
|
|
|
|
* expected type |
|
|
|
|
* @see #getRequiredAttribute(String, Class) |
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
private <T> T getAttribute(String attributeName, Class<T> expectedType) { |
|
|
|
|
Object value = get(attributeName); |
|
|
|
|
if (value != null) { |
|
|
|
|
assertAttributeType(attributeName, value, expectedType); |
|
|
|
|
} |
|
|
|
|
return (T) value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -340,7 +418,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -340,7 +418,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
* if it is not of the expected type |
|
|
|
|
*/ |
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
private <T> T doGet(String attributeName, Class<T> expectedType) { |
|
|
|
|
private <T> T getRequiredAttribute(String attributeName, Class<T> expectedType) { |
|
|
|
|
Assert.hasText(attributeName, "attributeName must not be null or empty"); |
|
|
|
|
Object value = get(attributeName); |
|
|
|
|
assertAttributePresence(attributeName, value); |
|
|
|
|
@ -378,14 +456,6 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
@@ -378,14 +456,6 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String[] getStringArrayWithoutNullCheck(String attributeName) { |
|
|
|
|
Object value = get(attributeName); |
|
|
|
|
if (value != null) { |
|
|
|
|
assertAttributeType(attributeName, value, String[].class); |
|
|
|
|
} |
|
|
|
|
return (String[]) value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Store the supplied {@code value} in this map under the specified |
|
|
|
|
* {@code key}, unless a value is already stored under the key. |
|
|
|
|
|