Package org.jrebirth.af.core.link

Source Code of org.jrebirth.af.core.link.ComponentEnhancer

/**
* Get more info at : www.jrebirth.org .
* Copyright JRebirth.org © 2011-2013
* Contact : sebastien.bordes@jrebirth.org
*
* 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 org.jrebirth.af.core.link;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jrebirth.af.core.annotation.AfterInit;
import org.jrebirth.af.core.annotation.BeforeInit;
import org.jrebirth.af.core.annotation.Component;
import org.jrebirth.af.core.annotation.OnRelease;
import org.jrebirth.af.core.annotation.SkipAnnotation;
import org.jrebirth.af.core.command.Command;
import org.jrebirth.af.core.exception.CoreException;
import org.jrebirth.af.core.facade.FacadeReady;
import org.jrebirth.af.core.facade.WaveReady;
import org.jrebirth.af.core.service.Service;
import org.jrebirth.af.core.ui.Model;
import org.jrebirth.af.core.util.ClassUtility;
import org.jrebirth.af.core.wave.OnWave;
import org.jrebirth.af.core.wave.WaveType;
import org.jrebirth.af.core.wave.WaveTypeBase;

/**
* The class <strong>ComponentEnhancer</strong> is an utility class used to manage Components Annotations.
*
* @author Sébastien Bordes
*/
public class ComponentEnhancer {

    /**
     * Private Constructor.
     */
    private ComponentEnhancer() {
        // Nothing to do
    }

    /**
     * Check if annotation can be processed for the given class.
     *
     * @param componentClass the class to check
     *
     * @return true if annotation can be processed
     */
    public static boolean canProcessAnnotation(final Class<? extends WaveReady<?>> componentClass) {

        final SkipAnnotation skip = ClassUtility.getLastClassAnnotation(componentClass, SkipAnnotation.class);

        // No annotation or annotation deactivated ==> skip annotation processing
        return !(skip == null || skip.value());
    }

    /**
     * Inject component.
     *
     * @param component the component
     */
    public static void injectComponent(final WaveReady<?> component) {

        // Retrieve all fields annotated with Multiton
        for (final Field field : ClassUtility.getAnnotatedFields(component.getClass(), Component.class)) {
            inject(component, field, field.getAnnotation(Component.class).value());
        }

    }

    /**
     * Inject a component into the property of an other.
     *
     * @param component the component
     * @param field the field
     * @param keyParts the key parts
     */
    @SuppressWarnings("unchecked")
    private static void inject(final FacadeReady<?> component, final Field field, final Object... keyParts) {

        try {
            if (Command.class.isAssignableFrom(field.getType())) {
                ClassUtility.setFieldValue(field, component, component.getLocalFacade().getGlobalFacade().getCommandFacade().retrieve((Class<Command>) field.getType(), keyParts));
            } else if (Service.class.isAssignableFrom(field.getType())) {
                ClassUtility.setFieldValue(field, component, component.getLocalFacade().getGlobalFacade().getServiceFacade().retrieve((Class<Service>) field.getType(), keyParts));
            } else if (Model.class.isAssignableFrom(field.getType())) {
                ClassUtility.setFieldValue(field, component, component.getLocalFacade().getGlobalFacade().getUiFacade().retrieve((Class<Model>) field.getType(), keyParts));
            }
        } catch (IllegalArgumentException | CoreException e) {
            e.printStackTrace();
        }

    }

    /**
     * Parse all method to search annotated methods that are attached to a lifecylce phase.
     *
     * @param component the JRebirth component to manage
     *
     * @return the map that store all method that sdhould be call sorted by lefecycle phase
     */
    public static Map<String, List<Method>> defineLifecycleMethod(final WaveReady<?> component) {

        final Map<String, List<Method>> lifecycleMethod = new HashMap<>();

        manageLifecycleAnnotation(component, lifecycleMethod, BeforeInit.class);
        manageLifecycleAnnotation(component, lifecycleMethod, AfterInit.class);
        manageLifecycleAnnotation(component, lifecycleMethod, OnRelease.class);

        return lifecycleMethod;
    }

    /**
     * Store annotated method related to a lifecycle phase.
     *
     * @param component the JRebirth component to manage
     * @param lifecycleMethod the map that store methods
     * @param annotationClass the annotation related to lifecycle phase
     */
    private static void manageLifecycleAnnotation(final WaveReady<?> component, final Map<String, List<Method>> lifecycleMethod, final Class<? extends Annotation> annotationClass) {
        for (final Method method : ClassUtility.getAnnotatedMethods(component.getClass(), annotationClass)) {
            if (!lifecycleMethod.containsKey(annotationClass.getName())) {
                lifecycleMethod.put(annotationClass.getName(), new ArrayList<Method>());
            }
            lifecycleMethod.get(annotationClass.getName()).add(method); // TODO sort
        }
    }

    /**
     * Manage {@link OnWave} annotation (defined on type and method).
     *
     * @param component the wave ready
     */
    public static void manageOnWaveAnnotation(final WaveReady<?> component) {

        // Retrieve class annotation
        final OnWave clsOnWave = component.getClass().getAnnotation(OnWave.class);
        if (clsOnWave != null) {
            manageUniqueWaveTypeAction(component, clsOnWave.value(), null);
            manageMultipleWaveTypeAction(component, clsOnWave, null);
        }

        // Iterate over each annotated Method
        OnWave onWave = null;
        for (final Method method : ClassUtility.getAnnotatedMethods(component.getClass(), OnWave.class)) {
            onWave = method.getAnnotation(OnWave.class);
            manageUniqueWaveTypeAction(component, onWave.value(), method);
            manageMultipleWaveTypeAction(component, onWave, method);
        }

    }

    /**
     * Manage unique {@link WaveType} subscription (from value field of {@link OnWave} annotation).
     *
     * @param component the wave ready
     * @param waveActionName the {@link WaveType} unique name
     * @param method the wave handler method
     */
    private static void manageUniqueWaveTypeAction(final WaveReady<?> component, final String waveActionName, final Method method) {

        // Get the WaveType from the WaveType registry
        final WaveType wt = WaveTypeBase.getWaveType(waveActionName);
        if (wt != null) {
            // Method is not defined or is the default fallback one
            if (method == null || AbstractWaveReady.PROCESS_WAVE_METHOD_NAME.equals(method.getName())) {
                // Just listen the WaveType
                component.listen(wt);
            } else {
                // Listen the WaveType and specify the right method handler
                component.listen(null, method, wt);
            }
        }
    }

    /**
     * Manage several {@link WaveType} subscriptions (from types field of {@link OnWave} annotation).
     *
     * @param waveReady the wave ready
     * @param onWave the {@link OnWave} annotation to explore
     * @param method the wave handler method
     */
    private static void manageMultipleWaveTypeAction(final WaveReady<?> waveReady, final OnWave onWave, final Method method) {
        for (final String action : onWave.types()) {
            manageUniqueWaveTypeAction(waveReady, action, method);
        }
    }

}
TOP

Related Classes of org.jrebirth.af.core.link.ComponentEnhancer

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.