All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.weaver.model.Weavable Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.commons.weaver.model;

import java.lang.annotation.Annotation;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * {@link Weavable} extends {@link AnnotatedElement} to include
 * {@link RetentionPolicy#CLASS} annotations.
 *
 * @param  own type
 * @param  target type
 */
public abstract class Weavable, TARGET> implements Comparable,
    AnnotatedElement {
    private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];

    private final TARGET target;
    private Set annotations;

    /**
     * Create a new {@link Weavable} instance.
     * @param target {@code TARGET}
     */
    protected Weavable(final TARGET target) {
        this.target = target;
        if (target instanceof AnnotatedElement) {
            addAnnotations(((AnnotatedElement) target).getAnnotations());
        }
    }

    /**
     * Add one or more annotations.
     * @param toAdd {@link Annotation}[]
     * @return whether any change was made
     */
    public final boolean addAnnotations(final Annotation... toAdd) {
        Validate.noNullElements(toAdd);
        return addAnnotations(Arrays.asList(toAdd));
    }

    /**
     * Add annotations from an {@link Iterable}.
     * @param toAdd {@link Iterable} of {@link Annotation}
     * @return whether any change was made
     */
    public final boolean addAnnotations(final Iterable toAdd) {
        if (toAdd == null) {
            return false;
        }
        synchronized (this) {
            if (annotations == null) {
                annotations = new LinkedHashSet();
            }
            boolean result = false;
            for (final Annotation ann : toAdd) {
                if (ann == null) {
                    continue;
                }
                result = annotations.add(ann) || result;
            }
            return result;
        }
    }

    /**
     * Get the target of this {@link Weavable}.
     * @return {@code TARGET}
     */
    public TARGET getTarget() {
        return target;
    }

    /**
     * Get all {@link Annotation}s associated with this element.
     * @return {@link Annotation}[]
     */
    @Override
    public final synchronized Annotation[] getAnnotations() {
        if (annotations == null) {
            return EMPTY_ANNOTATION_ARRAY; //NOPMD - no problem sharing zero-length array
        }
        return annotations.toArray(new Annotation[annotations.size()]);
    }

    /**
     * Get any instance of {@code annotationClass} attached to {@link #getTarget()}.
     * @param annotationClass {@link Class} annotation type
     * @param  annotation type
     * @return {@code T} instance if available, else {@code null}
     */
    @Override
    public synchronized  T getAnnotation(final Class annotationClass) {
        if (annotations == null) {
            return null;
        }
        for (final Annotation prospect : annotations) {
            if (annotationClass.equals(prospect.annotationType())) {
                @SuppressWarnings("unchecked")
                final T result = (T) prospect;
                return result;
            }
        }
        return null;
    }

    /**
     * Overridden to return {@link #getAnnotations()}.
     * @return {@link Annotation}[]
     */
    @Override
    public final Annotation[] getDeclaredAnnotations() {
        return getAnnotations();
    }

    /**
     * Learn whether an annotation of type {@code annotationClass} is present.
     * @param annotationClass to find
     * @return {@code boolean}
     */
    @Override
    public boolean isAnnotationPresent(final Class annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

    /**
     * Return a {@link String} representation of this {@link Weavable}.
     * @return {@link String}
     */
    @Override
    public String toString() {
        return "Weavable " + getTarget().toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (!getClass().isInstance(obj)) {
            return false;
        }
        return getTarget().equals(((Weavable) obj).getTarget());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(getTarget()).toHashCode();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy