Package org.springframework.roo.classpath.details

Source Code of org.springframework.roo.classpath.details.AbstractIdentifiableAnnotatedJavaStructureBuilder

package org.springframework.roo.classpath.details;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.Validate;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.model.Builder;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;

/**
* Assists in the creation of a {@link Builder} for types that eventually
* implement {@link IdentifiableAnnotatedJavaStructure}.
*
* @author Ben Alex
* @since 1.1
*/
public abstract class AbstractIdentifiableAnnotatedJavaStructureBuilder<T extends IdentifiableAnnotatedJavaStructure>
        extends AbstractIdentifiableJavaStructureBuilder<T> {
    private List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>();

    protected AbstractIdentifiableAnnotatedJavaStructureBuilder(
            final IdentifiableAnnotatedJavaStructure existing) {
        super(existing);
        init(existing);
    }

    protected AbstractIdentifiableAnnotatedJavaStructureBuilder(
            final String declaredbyMetadataId) {
        super(declaredbyMetadataId);
    }

    protected AbstractIdentifiableAnnotatedJavaStructureBuilder(
            final String declaredbyMetadataId,
            final IdentifiableAnnotatedJavaStructure existing) {
        super(declaredbyMetadataId, existing);
        init(existing);
    }

    public final boolean addAnnotation(
            final AnnotationMetadata annotationMetadata) {
        if (annotationMetadata == null) {
            return false;
        }
        return addAnnotation(new AnnotationMetadataBuilder(annotationMetadata));
    }

    public final boolean addAnnotation(
            final AnnotationMetadataBuilder annotationBuilder) {
        if (annotationBuilder == null) {
            return false;
        }
        onAddAnnotation(annotationBuilder);
        return annotations.add(annotationBuilder);
    }

    public final List<AnnotationMetadata> buildAnnotations() {
        final List<AnnotationMetadata> result = new ArrayList<AnnotationMetadata>();
        for (final AnnotationMetadataBuilder annotationBuilder : annotations) {
            result.add(annotationBuilder.build());
        }
        return result;
    }

    public final List<AnnotationMetadataBuilder> getAnnotations() {
        return annotations;
    }

    /**
     * Locates the specified type-level annotation.
     *
     * @param type to locate (can be <code>null</code>)
     * @return the annotation, or null if not found
     * @since 1.2.0
     */
    public AnnotationMetadataBuilder getDeclaredTypeAnnotation(
            final JavaType type) {
        for (final AnnotationMetadataBuilder annotationBuilder : getAnnotations()) {
            if (annotationBuilder.getAnnotationType().equals(type)) {
                return annotationBuilder;
            }
        }
        return null;
    }

    private void init(final IdentifiableAnnotatedJavaStructure existing) {
        for (final AnnotationMetadata element : existing.getAnnotations()) {
            this.annotations.add(new AnnotationMetadataBuilder(element));
        }
    }

    protected void onAddAnnotation(
            final AnnotationMetadataBuilder annotationMetadata) {
    }

    public void removeAnnotation(final JavaType annotationType) {
        for (final AnnotationMetadataBuilder annotationMetadataBuilder : annotations) {
            if (annotationMetadataBuilder.getAnnotationType().equals(
                    annotationType)) {
                annotations.remove(annotationMetadataBuilder);
                break;
            }
        }
    }

    public final void setAnnotations(
            final Collection<AnnotationMetadata> annotations) {
        final List<AnnotationMetadataBuilder> annotationBuilders = new ArrayList<AnnotationMetadataBuilder>();
        for (final AnnotationMetadata annotationMetadata : annotations) {
            annotationBuilders.add(new AnnotationMetadataBuilder(
                    annotationMetadata));
        }
        setAnnotations(annotationBuilders);
    }

    public final void setAnnotations(
            final List<AnnotationMetadataBuilder> annotations) {
        this.annotations = annotations;
    }

    public boolean updateTypeAnnotation(final AnnotationMetadata annotation) {
        return updateTypeAnnotation(annotation, null);
    }

    public boolean updateTypeAnnotation(final AnnotationMetadata annotation,
            final Set<JavaSymbolName> attributesToDeleteIfPresent) {
        boolean hasChanged = false;

        // We are going to build a replacement AnnotationMetadata.
        // This variable tracks the new attribute values the replacement will
        // hold.
        final Map<JavaSymbolName, AnnotationAttributeValue<?>> replacementAttributeValues = new LinkedHashMap<JavaSymbolName, AnnotationAttributeValue<?>>();

        final AnnotationMetadataBuilder existingBuilder = getDeclaredTypeAnnotation(annotation
                .getAnnotationType());

        if (existingBuilder == null) {
            // Not already present, so just go and add it
            for (final JavaSymbolName incomingAttributeName : annotation
                    .getAttributeNames()) {
                // Do not copy incoming attributes which exist in the
                // attributesToDeleteIfPresent Set
                if (attributesToDeleteIfPresent == null
                        || !attributesToDeleteIfPresent
                                .contains(incomingAttributeName)) {
                    final AnnotationAttributeValue<?> incomingValue = annotation
                            .getAttribute(incomingAttributeName);
                    replacementAttributeValues.put(incomingAttributeName,
                            incomingValue);
                }
            }

            final AnnotationMetadataBuilder replacement = new AnnotationMetadataBuilder(
                    annotation.getAnnotationType(),
                    new ArrayList<AnnotationAttributeValue<?>>(
                            replacementAttributeValues.values()));
            addAnnotation(replacement);
            return true;
        }

        final AnnotationMetadata existing = existingBuilder.build();

        // Copy the existing attributes into the new attributes
        for (final JavaSymbolName existingAttributeName : existing
                .getAttributeNames()) {
            if (attributesToDeleteIfPresent != null
                    && attributesToDeleteIfPresent
                            .contains(existingAttributeName)) {
                hasChanged = true;
            }
            else {
                final AnnotationAttributeValue<?> existingValue = existing
                        .getAttribute(existingAttributeName);
                replacementAttributeValues.put(existingAttributeName,
                        existingValue);
            }
        }

        // Now we ensure every incoming attribute replaces the existing
        for (final JavaSymbolName incomingAttributeName : annotation
                .getAttributeNames()) {
            final AnnotationAttributeValue<?> incomingValue = annotation
                    .getAttribute(incomingAttributeName);

            // Add this attribute to the end of the list if the attribute is not
            // already present
            if (replacementAttributeValues.keySet().contains(
                    incomingAttributeName)) {
                // There was already an attribute. Need to determine if this new
                // attribute value is materially different
                final AnnotationAttributeValue<?> existingValue = replacementAttributeValues
                        .get(incomingAttributeName);
                Validate.notNull(existingValue,
                        "Existing value should have been provided by earlier loop");
                if (!existingValue.equals(incomingValue)) {
                    replacementAttributeValues.put(incomingAttributeName,
                            incomingValue);
                    hasChanged = true;
                }
            }
            else if (attributesToDeleteIfPresent == null
                    || !attributesToDeleteIfPresent
                            .contains(incomingAttributeName)) {
                // This is a new attribute that does not already exist, so add
                // it to the end of the replacement attributes
                replacementAttributeValues.put(incomingAttributeName,
                        incomingValue);
                hasChanged = true;
            }
        }
        // Were there any material changes?
        if (!hasChanged) {
            return false;
        }

        // Make a new AnnotationMetadata representing the replacement
        final AnnotationMetadataBuilder replacement = new AnnotationMetadataBuilder(
                annotation.getAnnotationType(),
                new ArrayList<AnnotationAttributeValue<?>>(
                        replacementAttributeValues.values()));
        annotations.remove(existingBuilder);
        addAnnotation(replacement);

        return true;
    }

    public boolean updateTypeAnnotation(
            final AnnotationMetadataBuilder annotationBuilder) {
        return updateTypeAnnotation(annotationBuilder.build());
    }
}
TOP

Related Classes of org.springframework.roo.classpath.details.AbstractIdentifiableAnnotatedJavaStructureBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.