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

com.exadel.aem.toolkit.plugin.metadata.Metadata Maven / Gradle / Ivy

Go to download

Maven plugin for storing AEM (Granite UI) markup created with Exadel Toolbox Authoring Kit

There is a newer version: 2.5.3
Show newest version
/*
 * Licensed 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 com.exadel.aem.toolkit.plugin.metadata;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Spliterator;
import java.util.stream.Stream;

import com.exadel.aem.toolkit.plugin.maven.PluginRuntime;

/**
 * Represents a generic metadata object intended to retrieve, modify, and store Java annotations properties via
 * invocation handling
 * @see MetadataHandler
 * @see Property
 */
public interface Metadata extends Annotation, Iterable {

    /**
     * Retrieves a meta-annotation of the annotation represented by the current {@code Metadata} instance by its type
     * @param type {@code Class} reference, not null
     * @param   Type of the annotation to retrieve
     * @return {@code Annotation} instance, or null if not found
     */
     T getAnnotation(Class type);

    /**
     * Retrieves the first meta-annotation of the annotation represented by the current {@code Metadata} instance that
     * matches any of the provided types
     * @param types One or more non-null {@code Class} references
     * @return {@code Annotation} instance, or null if no match is found
     */
    Annotation getAnyAnnotation(Class... types);

    /**
     * Gets whether the annotation reflected by the current object has a property specified by the path. The path can be
     * either a simple name or a tree-like comma-delimited or slash-delimited structure
     * @param path Path to the property: a dot-delimited or slash-delimited string
     * @return True or false
     * @see PropertyPath
     */
    boolean hasProperty(String path);

    /**
     * Retrieves a property of the annotation represented by the current {@code Metadata} instance by its path
     * @param path Path to the property: a dot-delimited or slash-delimited string
     * @return {@link Property} instance, or null if not found
     */
    Property getProperty(String path);

    /**
     * Retrieves a property of the annotation represented by the current {@code Metadata} instance by its path
     * @param path Path to the property as a {@link PropertyPath} instance
     * @return {@link Property} instance, or null if not found
     */
    Property getProperty(PropertyPath path);

    /**
     * Retrieves the value of a property of the annotation represented by the current {@code Metadata} instance by its
     * path
     * @param path Path to the property: a dot-delimited or slash-delimited string
     * @return Arbitrary nullable object
     */
    Object getValue(String path);

    /**
     * Retrieves the value of a property of the annotation represented by the current {@code Metadata} instance by its
     * path
     * @param path Path to the property as a {@link PropertyPath} instance
     * @return Arbitrary nullable object
     */
    Object getValue(PropertyPath path);

    /**
     * Modifies the value of a property of the annotation represented by the current {@code Metadata} instance by
     * storing a makeshift substitution value
     * @param path  Path to the property: a dot-delimited or slash-delimited string
     * @param value Arbitrary nullable object
     * @return The modified value
     */
    Object putValue(String path, Object value);

    /**
     * Modifies the value of a property of the annotation represented by the current {@code Metadata} instance by
     * storing a makeshift substitution value
     * @param path  Path to the property as a {@link PropertyPath} instance
     * @param value Arbitrary nullable object
     * @return The modified value
     */
    Object putValue(PropertyPath path, Object value);

    /**
     * Removes the makeshift value for the property of the annotation represented by the current {@code Metadata}
     * instance
     * @param path Path to the property: a dot-delimited or slash-delimited string
     * @return The removed value
     */
    @SuppressWarnings("UnusedReturnValue")
    Object unsetValue(String path);

    /**
     * Retrieves an {@code Iterator} over the properties of the annotation represented by the current {@code Metadata}
     * @param deepRead     {@code True} to iterate over the properties of nested annotations, if there are any
     * @param expandArrays {@code True} to expand array properties into separate yielded items
     * @return {@code Iterator} instance
     */
    Iterator iterator(boolean deepRead, boolean expandArrays);

    /**
     * Retrieves a {@code Spliterator} over the properties of the annotation represented by the current
     * {@code Metadata}
     * @param deepRead     {@code True} to iterate over the properties of nested annotations, if there are any
     * @param expandArrays {@code True} to expand array properties into separate yielded items
     * @return {@code Spliterator} instance
     */
    Spliterator spliterator(boolean deepRead, boolean expandArrays);

    /**
     * Retrieves a {@code Stream} that returns properties of the annotation represented by the current {@code Metadata}.
     * No deep-read or array destructuring is done
     * @return {@code Stream} instance
     */
    Stream stream();

    /**
     * Retrieves a {@code Stream} over the properties of the annotation represented by the current {@code Metadata}
     * @param deepRead     {@code True} to iterate over the properties of nested annotations, if there are any
     * @param expandArrays {@code True} to expand array properties into separate yielded items
     * @return {@code Stream} instance
     */
    Stream stream(boolean deepRead, boolean expandArrays);

    /**
     * Creates a {@link Metadata}-based annotation proxy for the given annotation type
     * @param type {@code Class} reference, not null
     * @param   Type of the annotation to retrieve
     * @return {@code Metadata}-based @code Annotation} instance
     */
    static  T from(Class type) {
        return from(type, Collections.emptyMap());
    }

    /**
     * Creates a {@link Metadata}-based annotation proxy for the given annotation type exposing the provided property
     * values
     * @param type       {@code Class} reference, not null
     * @param properties Map of properties to expose
     * @param         Type of the annotation to retrieve
     * @return {@code Metadata}-based @code Annotation} instance
     */
    @SuppressWarnings("unchecked")
    static  T from(Class type, Map properties) {
        return (T) from(null, type, properties);
    }

    /**
     * Creates a {@link Metadata}-based object for the given source annotation
     * @param source {@code Annotation} object
     * @param   Type of the annotation
     * @return {@code Metadata} instance
     */
    static  Metadata from(T source) {
        return from(source, null, null);
    }

    /**
     * Creates a {@link Metadata}-based object for the given source annotation and overriding property values
     * @param source {@code Annotation} object, not null
     * @param properties Map of properties to expose
     * @param   Type of the annotation
     * @return {@code Metadata} instance
     */
    static  Metadata from(T source, Map properties) {
        return from(source, null, properties);
    }

    /**
     * Creates a {@link Metadata}-based object for the given source annotation, type, and overriding property values
     * @param source A nullable {@code Annotation} object
     * @param type {@code Class} reference. Must not be null if {@code source} is null
     * @param properties Map of properties to expose
     * @param   Type of the annotation
     * @return {@code Metadata} instance
     */
    static  Metadata from(T source, Class type, Map properties) {
        if (source instanceof Metadata) {
            if (properties != null && !properties.isEmpty()) {
                properties.forEach((key, value) -> ((Metadata) source).putValue(key, value));
            }
            return (Metadata) source;
        }
        Class effectiveType = source != null ? source.annotationType() : type;
        MetadataHandler interfaceHandler = source != null
            ? new MetadataHandler<>(source, properties)
            : new MetadataHandler<>(type, properties);
        Object newInstance = Proxy.newProxyInstance(
            PluginRuntime.context().getReflection().getClassLoader(),
            new Class[]{effectiveType, Metadata.class},
            interfaceHandler);
        return (Metadata) newInstance;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy