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

com.composum.platform.models.adapter.PropertyJoinedWithDefaultsWrapper Maven / Gradle / Ivy

package com.composum.platform.models.adapter;

import com.composum.platform.models.annotations.*;
import com.composum.sling.core.InheritedValues;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.slf4j.Logger;

import javax.annotation.Nonnull;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Wrapper for {@link Property} annotation that supplements it with the defaults from the {@link PropertyDefaults}
 * annotation.
 *
 * @author Hans-Peter Stoerr
 * @since 09/2017
 */
@SuppressWarnings("ClassExplicitlyAnnotation")
class PropertyJoinedWithDefaultsWrapper implements Property, PropertyDetermineResourceStrategy {

    private static final Logger LOG = getLogger(PropertyJoinedWithDefaultsWrapper.class);
    protected static PropertyDefaults defaultForPropertyDefaults =
            Defaulted.class.getAnnotation(PropertyDefaults.class);
    protected static Property defaultForProperty;

    static {
        try {
            defaultForProperty = Defaulted.class.getDeclaredMethod("getDefault").getAnnotation(Property.class);
        } catch (NoSuchMethodException e) {
            LOG.error("Impossible: " + e, e);
            throw new ExceptionInInitializerError(e);
        }
    }

    private final Property propertyAnnotation;
    private final PropertyDefaults propertyDefaultsAnnotation;
    private final PropertyDetermineResourceStrategy determineResourceStrategy;

    protected PropertyJoinedWithDefaultsWrapper(Property propertyAnnotation, PropertyDefaults
            propertyDefaultsAnnotation, PropertyDetermineResourceStrategy determineResourceStrategy) {
        this.propertyAnnotation = propertyAnnotation;
        this.propertyDefaultsAnnotation = null != propertyDefaultsAnnotation ? propertyDefaultsAnnotation :
                defaultForPropertyDefaults;
        this.determineResourceStrategy = determineResourceStrategy;
    }

    /**
     * Returns a wrapper that is instance of the {@link Property} annotation that supplements values with the defaults
     * of a {@link PropertyDefaults} annotation found at the class where element is declared or its superclasses, as
     * well as an instance of {@link PropertyDetermineResourceStrategy} found similarly.
     *
     * @param element the element
     * @return the with defaults, or null if there is no {@link Property} annotation
     */
    public static PropertyJoinedWithDefaultsWrapper getWithDefaults(@Nonnull AnnotatedElement element) {
        Property propertyAnnotation = element.getAnnotation(Property.class);
        if (null == propertyAnnotation) return null;
        Class declaringClass = null;
        if (element instanceof Member) { // this doesn't work with parameters, so we can't allow @Property on those.
            declaringClass = ((Member) element).getDeclaringClass();
        } else {
            LOG.warn("Bug: Couldn't determine declaring class for {}, skipping PropertyDefaults.", element.getClass());
        }
        PropertyDefaults propertyDefaults = null;
        PropertyDetermineResourceStrategy determineResourceStrategy = null;
        while (null != declaringClass) { // go to parents in case of inner classes
            if (null == propertyDefaults) propertyDefaults = declaringClass.getAnnotation(PropertyDefaults.class);
            if (null == determineResourceStrategy) determineResourceStrategy =
                    declaringClass.getAnnotation(PropertyDetermineResourceStrategy.class);
            declaringClass = declaringClass.getDeclaringClass();
        }
        return new PropertyJoinedWithDefaultsWrapper(propertyAnnotation, propertyDefaults, determineResourceStrategy);
    }

    @Override
    public String name() {
        return propertyAnnotation.name();
    }

    @Override
    public String basePath() {
        return propertyAnnotation.basePath();
    }

    @Override
    public boolean inherited() {
        return propertyAnnotation.inherited();
    }

    @Override
    public InheritedValues.Type inheritanceType() {
        return propertyAnnotation.inheritanceType() != defaultForProperty.inheritanceType() ?
                propertyAnnotation.inheritanceType() : propertyDefaultsAnnotation.inheritanceType();
    }

    @Override
    public InjectionStrategy injectionStrategy() {
        return propertyAnnotation.injectionStrategy();
    }

    @Override
    public String via() {
        return propertyAnnotation.via();
    }

    @Override
    public boolean i18n() {
        return propertyAnnotation.i18n();
    }

    @Override
    public Class i18nStrategy() {
        return propertyAnnotation.i18nStrategy() != defaultForProperty.i18nStrategy() ?
                propertyAnnotation.i18nStrategy() : propertyDefaultsAnnotation.i18nStrategy();
    }

    @Override
    public Class value() {
        return null != determineResourceStrategy ? determineResourceStrategy.value() :
                DetermineResourceStategy.OriginalResourceStrategy.class;
    }

    @Override
    public Class annotationType() {
        return propertyAnnotation.annotationType();
    }

    /** Class to easily read the defaults of the annotations. */
    @PropertyDefaults
    protected interface Defaulted {
        @Property
        void getDefault();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy