package org.springframework.roo.classpath.customdata.taggers; import static org.springframework.roo.classpath.customdata.CustomDataKeys.COLUMN_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.EMBEDDED_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.EMBEDDED_ID_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.ENUMERATED_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.IDENTIFIER_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.LOB_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.MANY_TO_MANY_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.MANY_TO_ONE_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.ONE_TO_MANY_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.ONE_TO_ONE_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.TRANSIENT_FIELD; import static org.springframework.roo.classpath.customdata.CustomDataKeys.VERSION_FIELD; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_COLUMN_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_EMBEDDED_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_EMBEDDED_ID_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_ENUMERATED_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_ID_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_LOB_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_MANY_TO_MANY_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_MANY_TO_ONE_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_ONE_TO_MANY_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_ONE_TO_ONE_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_TRANSIENT_ANNOTATION; import static org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder.JPA_VERSION_ANNOTATION; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.Validate; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.MemberHoldingTypeDetails; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.model.CustomDataKey; import org.springframework.roo.model.JavaSymbolName; /** * A {@link Matcher} for {@link FieldMetadata}-that matches on the presence of * at least one of a given list of annotations. * * @author James Tyrrell * @author Andrew Swan * @since 1.1.3 */ public class FieldMatcher implements Matcher<FieldMetadata> { public static final FieldMatcher JPA_COLUMN = new FieldMatcher(COLUMN_FIELD, JPA_COLUMN_ANNOTATION); public static final FieldMatcher JPA_EMBEDDED = new FieldMatcher(EMBEDDED_FIELD, JPA_EMBEDDED_ANNOTATION); public static final FieldMatcher JPA_EMBEDDED_ID = new FieldMatcher(EMBEDDED_ID_FIELD, JPA_EMBEDDED_ID_ANNOTATION); public static final FieldMatcher JPA_ENUMERATED = new FieldMatcher(ENUMERATED_FIELD, JPA_ENUMERATED_ANNOTATION); public static final FieldMatcher JPA_ID = new FieldMatcher(IDENTIFIER_FIELD, JPA_ID_ANNOTATION); public static final FieldMatcher JPA_LOB = new FieldMatcher(LOB_FIELD, JPA_LOB_ANNOTATION); public static final FieldMatcher JPA_MANY_TO_MANY = new FieldMatcher(MANY_TO_MANY_FIELD, JPA_MANY_TO_MANY_ANNOTATION); public static final FieldMatcher JPA_MANY_TO_ONE = new FieldMatcher(MANY_TO_ONE_FIELD, JPA_MANY_TO_ONE_ANNOTATION); public static final FieldMatcher JPA_ONE_TO_MANY = new FieldMatcher(ONE_TO_MANY_FIELD, JPA_ONE_TO_MANY_ANNOTATION); public static final FieldMatcher JPA_ONE_TO_ONE = new FieldMatcher(ONE_TO_ONE_FIELD, JPA_ONE_TO_ONE_ANNOTATION); public static final FieldMatcher JPA_TRANSIENT = new FieldMatcher(TRANSIENT_FIELD, JPA_TRANSIENT_ANNOTATION); public static final FieldMatcher JPA_VERSION = new FieldMatcher(VERSION_FIELD, JPA_VERSION_ANNOTATION); private final List<AnnotationMetadata> annotations; private final CustomDataKey<FieldMetadata> customDataKey; /** * Constructor for matching on any of the given annotations * * @param customDataKey the custom data key indicating the type of field * (required) * @param annotations the annotations to match upon * @since 1.2.0 */ public FieldMatcher(final CustomDataKey<FieldMetadata> customDataKey, final AnnotationMetadata... annotations) { this(customDataKey, Arrays.asList(annotations)); } /** * Constructor for matching on any of the given annotations * * @param customDataKey the custom data key indicating the type of field * (required) * @param annotations the annotations to match upon (can be null) */ public FieldMatcher(final CustomDataKey<FieldMetadata> customDataKey, final Collection<AnnotationMetadata> annotations) { Validate.notNull(customDataKey, "Custom data key is required"); this.annotations = new ArrayList<AnnotationMetadata>(); this.customDataKey = customDataKey; if (annotations != null) { this.annotations.addAll(annotations); } } private Map<String, Object> getAttributeMap(final FieldMetadata field) { final Map<String, Object> map = new HashMap<String, Object>(); final AnnotationMetadata annotationMetadata = getMatchingAnnotation(field); if (annotationMetadata != null) { for (final JavaSymbolName attributeName : annotationMetadata.getAttributeNames()) { map.put(attributeName.getSymbolName(), annotationMetadata.getAttribute(attributeName) .getValue()); } } return map; } public CustomDataKey<FieldMetadata> getCustomDataKey() { return customDataKey; } /** * Returns the first annotation of the given field that matches any of this * matcher's target annotations * * @param field the field whose annotations are to be checked (required) * @return */ private AnnotationMetadata getMatchingAnnotation(final FieldMetadata field) { for (final AnnotationMetadata fieldAnnotation : field.getAnnotations()) { for (final AnnotationMetadata matchingAnnotation : annotations) { if (fieldAnnotation.getAnnotationType().getFullyQualifiedTypeName() .equals(matchingAnnotation.getAnnotationType().getFullyQualifiedTypeName())) { return fieldAnnotation; } } } return null; } public Object getTagValue(final FieldMetadata field) { return getAttributeMap(field); } public List<FieldMetadata> matches( final List<MemberHoldingTypeDetails> memberHoldingTypeDetailsList) { final List<FieldMetadata> fields = new ArrayList<FieldMetadata>(); for (final MemberHoldingTypeDetails memberHoldingTypeDetails : memberHoldingTypeDetailsList) { for (final FieldMetadata field : memberHoldingTypeDetails.getDeclaredFields()) { if (getMatchingAnnotation(field) != null) { fields.add(field); } } } return fields; } }