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

com.teradata.tempto.internal.context.GuiceTestContext Maven / Gradle / Ivy

The 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.teradata.tempto.internal.context;

import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.teradata.tempto.context.State;
import com.teradata.tempto.context.TestContext;
import com.teradata.tempto.context.TestContextCloseCallback;
import org.slf4j.Logger;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.google.common.collect.ImmutableList.copyOf;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.inject.Guice.createInjector;
import static com.google.inject.name.Names.named;
import static com.google.inject.util.Modules.combine;
import static com.google.inject.util.Modules.override;
import static java.util.Collections.synchronizedList;
import static org.assertj.core.util.Lists.emptyList;
import static org.slf4j.LoggerFactory.getLogger;

public class GuiceTestContext
        implements TestContext
{
    private final static Logger LOGGER = getLogger(GuiceTestContext.class);

    private final Optional parent;
    private final List children = synchronizedList(newArrayList());
    private final Module baseModule;
    private final Map, State> states;
    private final Injector injector;
    private final List closeCallbacks = newArrayList();

    public GuiceTestContext(Module... baseModules)
    {
        this(Optional.empty(), combine(baseModules), newHashMap());
    }

    private GuiceTestContext(Optional parent, Module baseModule, Map, State> states)
    {
        this.parent = parent;
        this.baseModule = baseModule;
        this.states = states;
        this.injector = buildInjector();
    }

    @Override
    public  T getDependency(Class dependencyClass)
    {
        return getDependency(Key.get(dependencyClass));
    }

    @Override
    public  T getDependency(Class dependencyClass, String dependencyName)
    {
        return getDependency(Key.get(dependencyClass, named(dependencyName)));
    }

    private  T getDependency(Key key)
    {
        return (T) injector.getInstance(key);
    }

    @Override
    public  Optional getOptionalDependency(Class dependencyClass)
    {
        return getOptionalDependency(Key.get(dependencyClass));
    }

    @Override
    public  Optional getOptionalDependency(Class dependencyClass, String dependencyName)
    {
        return getOptionalDependency(Key.get(dependencyClass, named(dependencyName)));
    }

    public  Optional getOptionalDependency(Key key)
    {
        if (injector.getExistingBinding(key) != null) {
            return Optional.of(getDependency(key));
        }
        else {
            return Optional.empty();
        }
    }

    @Override
    public GuiceTestContext createChildContext(Iterable newStatesIterable)
    {
        return createChildContext(newStatesIterable, emptyList());
    }

    public GuiceTestContext createChildContext(Iterable newStatesIterable, Iterable overrideModules)
    {
        LOGGER.debug("Creating new test context from " + this);

        Map, State> newStates = newHashMap(states);
        for (State newState : newStatesIterable) {
            newStates.put(getKeyFor(newState), newState);
        }

        GuiceTestContext childTestContext = new GuiceTestContext(Optional.of(this), override(baseModule).with(overrideModules), newStates);
        children.add(childTestContext);
        return childTestContext;
    }

    @Override
    public void registerCloseCallback(TestContextCloseCallback callback)
    {
        closeCallbacks.add(callback);
    }

    @Override
    public void close()
    {
        copyOf(children).forEach(GuiceTestContext::close);
        Lists.reverse(closeCallbacks).forEach(callback -> callback.testContextClosed(this));

        if (parent.isPresent()) {
            parent.get().children.remove(this);
        }
    }

    public void injectMembers(Object instance)
    {
        injector.injectMembers(instance);
    }

    private Key getKeyFor(State state)
    {
        if (state.getName().isPresent()) {
            return Key.get((Class) state.getClass(), named(state.getName().get()));
        }
        else {
            return Key.get((Class) state.getClass());
        }
    }

    private Injector buildInjector()
    {
        return createInjector(combine(baseModule, statesModule(), testContextModule()));
    }

    private Module statesModule()
    {
        return (Binder binder) -> {
            for (Map.Entry, State> stateEntry : states.entrySet()) {
                binder.bind(stateEntry.getKey()).toInstance(stateEntry.getValue());
            }
        };
    }

    private Module testContextModule()
    {
        return (Binder binder) -> {
            binder.bind(TestContext.class).toInstance(this);
        };
    }

    public Injector getInjector()
    {
        return injector;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy