package org.springframework.roo.classpath.layers;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.springframework.roo.classpath.customdata.CustomDataKeys;
import org.springframework.roo.classpath.customdata.taggers.AnnotatedTypeMatcher;
import org.springframework.roo.classpath.customdata.taggers.Matcher;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.MemberHoldingTypeDetails;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.ArrayAttributeValue;
import org.springframework.roo.classpath.details.annotations.ClassAttributeValue;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
/**
* A {@link Matcher} used for layering support; identifies layer components
* (services, repositories, etc) by the presence of a given tag, and sets each
* such component's {@link CustomDataKeys#LAYER_TYPE} tag to a list of the
* domain types managed by that component (as a
* <code>List<{@link JavaType}></code>).
*
* @author Stefan Schmidt
* @since 1.2.0
*/
public class LayerTypeMatcher extends AnnotatedTypeMatcher {
private final JavaSymbolName domainTypesAttribute;
private final JavaType layerAnnotationType;
/**
* Constructor
*
* @param layerAnnotation the annotation type to match on and read
* attributes of (required)
* @param domainTypesAttribute the attribute of the above annotation that
* identifies the domain type(s) being managed (required)
*/
public LayerTypeMatcher(final JavaType layerAnnotation,
final JavaSymbolName domainTypesAttribute) {
super(CustomDataKeys.LAYER_TYPE, layerAnnotation);
Validate.notNull(layerAnnotation, "Layer annotation is required");
Validate.notNull(domainTypesAttribute,
"Domain types attribute is required");
this.domainTypesAttribute = domainTypesAttribute;
layerAnnotationType = layerAnnotation;
}
@Override
public Object getTagValue(final MemberHoldingTypeDetails type) {
final AnnotationMetadata layerAnnotation = MemberFindingUtils
.getAnnotationOfType(type.getAnnotations(), layerAnnotationType);
if (layerAnnotation == null
|| layerAnnotation.getAttribute(domainTypesAttribute) == null) {
return null;
}
final AnnotationAttributeValue<?> value = layerAnnotation
.getAttribute(domainTypesAttribute);
final List<JavaType> domainTypes = new ArrayList<JavaType>();
if (value instanceof ClassAttributeValue) {
domainTypes.add(((ClassAttributeValue) value).getValue());
}
else if (value instanceof ArrayAttributeValue<?>) {
final ArrayAttributeValue<?> castValue = (ArrayAttributeValue<?>) value;
for (final AnnotationAttributeValue<?> val : castValue.getValue()) {
if (val instanceof ClassAttributeValue) {
domainTypes.add(((ClassAttributeValue) val).getValue());
}
}
}
return domainTypes;
}
}