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

org.fluentlenium.core.hook.HookControlImpl Maven / Gradle / Ivy

package org.fluentlenium.core.hook;

import org.fluentlenium.core.FluentControl;
import org.fluentlenium.core.components.ComponentInstantiator;
import org.fluentlenium.core.proxy.LocatorProxies;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Control implementation for hooks.
 *
 * @param  self type
 */
public class HookControlImpl implements HookControl {
    private final List> hookDefinitions = new ArrayList<>();
    private Stack>> hookRestoreStack = new Stack<>();
    private final HookChainBuilder hookChainBuilder;

    private final T self;
    private final Object proxy;
    private final Supplier noHookInstanceSupplier;

    /**
     * Creates a new control implementation for hooks.
     *
     * @param self                   reference to object returned by chainnable calls
     * @param proxy                  proxy object to apply hooks on
     * @param control                control interface
     * @param instantiator           components instantiator
     * @param noHookInstanceSupplier supplier of new instance without any hook.
     */
    public HookControlImpl(T self, Object proxy, FluentControl control, ComponentInstantiator instantiator,
            Supplier noHookInstanceSupplier) {
        this.self = self;
        this.proxy = proxy;
        this.noHookInstanceSupplier = noHookInstanceSupplier;
        hookChainBuilder = new DefaultHookChainBuilder(control, instantiator);
    }

    /**
     * Get hook definitions.
     *
     * @return hook definitions
     */
    public List> getHookDefinitions() {
        return hookDefinitions;
    }

    /**
     * Get hook restore stack.
     *
     * @return hook restore stack
     */
    public Stack>> getHookRestoreStack() {
        return hookRestoreStack;
    }

    /**
     * Set the hook restore stack.
     *
     * @param hookRestoreStack hook restore stack
     */
    public void setHookRestoreStack(Stack>> hookRestoreStack) {
        this.hookRestoreStack = hookRestoreStack;
    }

    /**
     * Removes hooks from definitions.
     *
     * @param definitions   hook definitions
     * @param hooksToRemove hooks to remove
     */
    public static void removeHooksFromDefinitions(Collection> definitions,
            Class... hooksToRemove) {
        Iterator> hookDefinitionsIterator = definitions.iterator();
        List> toRemoveHooks = Arrays.asList(hooksToRemove);
        while (hookDefinitionsIterator.hasNext()) {
            HookDefinition next = hookDefinitionsIterator.next();
            if (toRemoveHooks.contains(next.getHookClass())) {
                hookDefinitionsIterator.remove();
            }
        }
    }

    private void backupHookDefinitions() {
        hookRestoreStack.add(new ArrayList<>(hookDefinitions));
    }

    private void restoreHookDefinitions() {
        if (!hookRestoreStack.isEmpty()) {
            List> pop = hookRestoreStack.pop();
            hookDefinitions.clear();
            hookDefinitions.addAll(pop);
        }
    }

    @Override
    public T restoreHooks() {
        restoreHookDefinitions();
        applyHooks(proxy, hookChainBuilder, hookDefinitions);
        return self;
    }

    @Override
    public > T withHook(Class hook) {
        hookDefinitions.add(new HookDefinition<>(hook));
        backupHookDefinitions();
        applyHooks(proxy, hookChainBuilder, hookDefinitions);
        return self;
    }

    @Override
    public > T withHook(Class hook, O options) {
        hookDefinitions.add(new HookDefinition<>(hook, options));
        backupHookDefinitions();
        applyHooks(proxy, hookChainBuilder, hookDefinitions);
        return self;
    }

    @Override
    public T noHook() {
        backupHookDefinitions();
        hookDefinitions.clear();
        applyHooks(proxy, hookChainBuilder, hookDefinitions);
        return self;
    }

    @Override
    public T noHook(Class... hooks) {
        backupHookDefinitions();
        removeHooksFromDefinitions(hookDefinitions, hooks);
        applyHooks(proxy, hookChainBuilder, hookDefinitions);
        return self;
    }

    /**
     * Apply defined hooks on the proxy.
     *
     * @param proxy            proxy
     * @param hookChainBuilder hook chain builder
     * @param hookDefinitions  hook definitions
     */
    protected void applyHooks(Object proxy, HookChainBuilder hookChainBuilder, List> hookDefinitions) {
        LocatorProxies.setHooks(proxy, hookChainBuilder, hookDefinitions);
    }

    @Override
    public  R noHook(Function function) {
        noHook();
        R functionReturn = function.apply(self);
        restoreHooks();
        return functionReturn;
    }

    @Override
    public  R noHook(Class hook, Function function) {
        noHook(hook);
        R functionReturn = function.apply(self);
        restoreHooks();
        return functionReturn;
    }

    @Override
    public T noHookInstance() {
        return ((HookControl) noHookInstanceSupplier.get()).noHook();
    }

    @Override
    public T noHookInstance(Class... hooks) {
        HookControl hookControl = (HookControl) noHookInstanceSupplier.get();

        for (HookDefinition definition : hookDefinitions) {
            hookControl.withHook(definition.getHookClass(), definition.getOptions());
        }

        return hookControl.noHook(hooks);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy