/*
* Copyright (c) 2015 NOVA, All rights reserved.
* This library is free software, licensed under GNU Lesser General Public License version 3
*
* This file is part of NOVA.
*
* NOVA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NOVA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NOVA. If not, see <http://www.gnu.org/licenses/>.
*/
package nova.internal.core.bootstrap;
import com.google.common.collect.Sets;
import nova.internal.core.Game;
import nova.internal.core.depmodules.CoreBundle;
import se.jbee.inject.Dependency;
import se.jbee.inject.Injector;
import se.jbee.inject.bootstrap.Bootstrap;
import se.jbee.inject.bootstrap.BootstrapperBundle;
import se.jbee.inject.bootstrap.Bundle;
import java.util.Optional;
import java.util.Set;
public class DependencyInjectionEntryPoint {
private State state = State.PREINIT;
private Optional<Injector> injector = Optional.empty();
private Set<Class<? extends Bundle>> bundles = Sets.newHashSet();
public DependencyInjectionEntryPoint() {
install(CoreBundle.class);
}
/**
* @return current injector instance.
*/
public Optional<Injector> getInjector() {
return injector;
}
/**
* @return current state.
*/
public State getState() {
return state;
}
/**
* Installs bundle in core Injector. Works until, finalization later throws
* {@link IllegalStateException}.
*
* @param bundle Bundle
*/
public void install(Class<? extends Bundle> bundle) {
if (state != State.PREINIT) {
throw new IllegalStateException("This function may only be used before DependencyInjectionEntryPoint initialization.");
}
bundles.add(bundle);
}
/**
* Removes bundle from core Injector. Works until finalization, later throws
* {@link IllegalStateException}.
*
* @param bundle Bundle
* @return whether module being uninstalled was installed.
*/
public boolean uninstall(Class<? extends Bundle> bundle) {
if (state != State.PREINIT) {
throw new IllegalStateException("This function may only be used before DependencyInjectionEntryPoint initialization.");
}
return bundles.remove(bundle);
}
/**
* In this method modules added to DependencyInjectionEntryPoint are being
* installed in core injector. Alternating module composition in core
* injector after initialization is not possible.
*
* @return Game instance {@link Game}. Use it for future injections and
* general management.
*/
public Game init() {
if (state != State.PREINIT) {
throw new IllegalStateException("EntryPoint#postInit() has to be only once.");
}
DIEPBundle.bundles = bundles;
injector = Optional.of(Bootstrap.injector(DIEPBundle.class));
state = State.POSTINIT;
return injector.map(injector -> injector.resolve(Dependency.dependency(Game.class))).orElseThrow(IllegalStateException::new);
}
private enum State {
PREINIT, POSTINIT
}
private static final class DIEPBundle extends BootstrapperBundle {
private static Set<Class<? extends Bundle>> bundles;
@Override
protected void bootstrap() {
bundles.stream().forEach(this::install);
}
}
}