feat(module): Implement module management system with loading, unloading, and state management
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root of all UI client modules
|
||||||
|
*/
|
||||||
|
public abstract class AbstractClientModule extends AbstractModule {
|
||||||
|
|
||||||
|
final static int MODULE_PRIORITY_LOW = 25;
|
||||||
|
|
||||||
|
final static int MODULE_PRIORITY_NORMAL = 50;
|
||||||
|
|
||||||
|
final static int MODULE_PRIORITY_HIGH = 75;
|
||||||
|
|
||||||
|
public AbstractClientModule() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return MODULE_PRIORITY_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlwaysDisplay() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onShow() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onHide() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runUiPreEvents() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runUiPostEvents() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root of all modules
|
||||||
|
*/
|
||||||
|
public abstract class AbstractModule {
|
||||||
|
|
||||||
|
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractModule.class);
|
||||||
|
|
||||||
|
public AbstractModule() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLoad() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUnload() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onActivate() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDeactivate() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getClass().getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
41
src/main/java/de/extio/game_engine/module/ModuleManager.java
Normal file
41
src/main/java/de/extio/game_engine/module/ModuleManager.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ModuleManager {
|
||||||
|
|
||||||
|
void loadModule(Class<? extends AbstractModule> clazz);
|
||||||
|
|
||||||
|
void unloadModule(Class<? extends AbstractModule> clazz);
|
||||||
|
|
||||||
|
List<AbstractModule> getModulesAll();
|
||||||
|
|
||||||
|
List<AbstractModule> getModulesActive();
|
||||||
|
|
||||||
|
List<AbstractClientModule> getModulesActiveClientModules();
|
||||||
|
|
||||||
|
List<AbstractClientModule> getModulesDisplayedClientModules();
|
||||||
|
|
||||||
|
void changeActiveState(String className, boolean active);
|
||||||
|
|
||||||
|
void changeActiveState(Class<? extends AbstractModule> clazz, boolean active);
|
||||||
|
|
||||||
|
void deactivateAll();
|
||||||
|
|
||||||
|
void changeDisplayState(String className, boolean active);
|
||||||
|
|
||||||
|
void changeDisplayState(Class<? extends AbstractClientModule> clazz, boolean display);
|
||||||
|
|
||||||
|
boolean isDisplayed(String className);
|
||||||
|
|
||||||
|
boolean isDisplayed(Class<? extends AbstractClientModule> clazz);
|
||||||
|
|
||||||
|
void hideAll();
|
||||||
|
|
||||||
|
void hideExcept(String... classNames);
|
||||||
|
|
||||||
|
void restoreVisibility();
|
||||||
|
|
||||||
|
boolean isModal();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
@AutoConfiguration
|
||||||
|
@ConditionalOnProperty(name = "game-engine.module.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public class ModuleManagerAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ModuleManager moduleManager(final List<AbstractModule> initialModules) {
|
||||||
|
return new ModuleManagerImpl(initialModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
297
src/main/java/de/extio/game_engine/module/ModuleManagerImpl.java
Normal file
297
src/main/java/de/extio/game_engine/module/ModuleManagerImpl.java
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
public class ModuleManagerImpl implements InitializingBean, ModuleManager {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
|
private final List<AbstractModule> modulesInitial;
|
||||||
|
|
||||||
|
private final List<AbstractModule> modulesAll = new ArrayList<>();
|
||||||
|
|
||||||
|
private List<AbstractModule> modulesAllView = List.of();
|
||||||
|
|
||||||
|
private List<AbstractModule> modulesActiveView = List.of();
|
||||||
|
|
||||||
|
private List<AbstractClientModule> modulesActiveClientModulesView = List.of();
|
||||||
|
|
||||||
|
private List<AbstractClientModule> modulesDisplayedClientModulesView = List.of();
|
||||||
|
|
||||||
|
private final List<AbstractModule> modulesActive = new ArrayList<>();
|
||||||
|
|
||||||
|
private final List<AbstractClientModule> modulesDisplayed = new ArrayList<>();
|
||||||
|
|
||||||
|
private final Deque<List<AbstractClientModule>> lastVisibleStates = new ArrayDeque<>();
|
||||||
|
|
||||||
|
public ModuleManagerImpl(final List<AbstractModule> initialModules) {
|
||||||
|
this.modulesInitial = initialModules;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
if (this.modulesInitial == null || this.modulesInitial.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.modulesInitial.forEach(module -> this.invokeSafe(module, AbstractModule::onLoad));
|
||||||
|
this.modulesAll.addAll(this.modulesInitial);
|
||||||
|
this.sortModules(this.modulesAll);
|
||||||
|
this.modulesAllView = List.copyOf(this.modulesAll);
|
||||||
|
this.modulesInitial.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractModule> getModulesAll() {
|
||||||
|
return this.modulesAllView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractModule> getModulesActive() {
|
||||||
|
return this.modulesActiveView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractClientModule> getModulesActiveClientModules() {
|
||||||
|
return this.modulesActiveClientModulesView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AbstractClientModule> getModulesDisplayedClientModules() {
|
||||||
|
return modulesDisplayedClientModulesView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadModule(final Class<? extends AbstractModule> clazz) {
|
||||||
|
if (this.modulesAll.stream().anyMatch(module -> clazz.isInstance(module))) {
|
||||||
|
LOGGER.debug("AbstractModule already loaded: " + clazz.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.debug("Loading module " + clazz.getName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
final AbstractModule module = AbstractModule.class.cast(clazz.getDeclaredConstructor().newInstance());
|
||||||
|
this.invokeSafe(module, m -> m.onLoad());
|
||||||
|
this.modulesAll.add(module);
|
||||||
|
this.sortModules(this.modulesAll);
|
||||||
|
this.modulesAllView = List.copyOf(this.modulesAll);
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
LOGGER.error("Error loading module " + clazz.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unloadModule(final Class<? extends AbstractModule> clazz) {
|
||||||
|
try {
|
||||||
|
final AbstractModule module = this.modulesAll.stream().filter(mod -> clazz.isInstance(mod)).findAny().orElse(null);
|
||||||
|
|
||||||
|
if (module == null) {
|
||||||
|
LOGGER.debug("AbstractModule not loaded: " + clazz.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.changeActiveState(clazz, false);
|
||||||
|
this.modulesAll.remove(module);
|
||||||
|
this.sortModules(this.modulesAll);
|
||||||
|
this.modulesAllView = List.copyOf(this.modulesAll);
|
||||||
|
|
||||||
|
this.invokeSafe(module, m -> m.onUnload());
|
||||||
|
|
||||||
|
LOGGER.debug("Unloaded module " + clazz.getName());
|
||||||
|
}
|
||||||
|
catch (final Exception e) {
|
||||||
|
LOGGER.error("Error unloading module " + clazz.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeActiveState(final String className, final boolean active) {
|
||||||
|
try {
|
||||||
|
final var clazz = Class.forName(className);
|
||||||
|
this.changeActiveState(clazz.asSubclass(AbstractModule.class), active);
|
||||||
|
}
|
||||||
|
catch (final ClassNotFoundException e) {
|
||||||
|
LOGGER.error("Class not found: " + className, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeActiveState(final Class<? extends AbstractModule> clazz, final boolean active) {
|
||||||
|
this.modulesActiveView.stream()
|
||||||
|
.filter(module -> clazz.isAssignableFrom(module.getClass()))
|
||||||
|
.findAny()
|
||||||
|
.ifPresentOrElse(module -> {
|
||||||
|
if (!active) {
|
||||||
|
if (module instanceof final AbstractClientModule clientModule) {
|
||||||
|
this.changeDisplayState(clientModule.getClass(), false);
|
||||||
|
}
|
||||||
|
this.invokeSafe(module, AbstractModule::onDeactivate);
|
||||||
|
this.modulesActive.remove(module);
|
||||||
|
this.sortModules(this.modulesActive);
|
||||||
|
this.modulesActiveView = List.copyOf(this.modulesActive);
|
||||||
|
this.modulesActiveClientModulesView = this.modulesActive.stream()
|
||||||
|
.filter(m -> m instanceof AbstractClientModule)
|
||||||
|
.map(m -> (AbstractClientModule) m)
|
||||||
|
.toList();
|
||||||
|
this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed);
|
||||||
|
|
||||||
|
LOGGER.debug("Deactivated " + clazz.getName());
|
||||||
|
}
|
||||||
|
}, () -> {
|
||||||
|
if (active) {
|
||||||
|
this.modulesAll.stream()
|
||||||
|
.filter(module -> clazz.isAssignableFrom(module.getClass()))
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(module -> {
|
||||||
|
this.invokeSafe(module, AbstractModule::onActivate);
|
||||||
|
if (module instanceof final AbstractClientModule clientModule && clientModule.isAlwaysDisplay()) {
|
||||||
|
this.changeDisplayState(clientModule.getClass(), true);
|
||||||
|
}
|
||||||
|
this.modulesActive.add(module);
|
||||||
|
this.sortModules(this.modulesActive);
|
||||||
|
this.modulesActiveView = List.copyOf(this.modulesActive);
|
||||||
|
this.modulesActiveClientModulesView = this.modulesActive.stream()
|
||||||
|
.filter(m -> m instanceof AbstractClientModule)
|
||||||
|
.map(m -> (AbstractClientModule) m)
|
||||||
|
.toList();
|
||||||
|
this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed);
|
||||||
|
|
||||||
|
LOGGER.debug("Activated " + clazz.getName());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivateAll() {
|
||||||
|
for (final AbstractModule module : this.modulesActiveView) {
|
||||||
|
this.changeActiveState(module.getClass(), false);
|
||||||
|
}
|
||||||
|
this.lastVisibleStates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeDisplayState(final String className, final boolean active) {
|
||||||
|
try {
|
||||||
|
final var clazz = Class.forName(className);
|
||||||
|
this.changeDisplayState(clazz.asSubclass(AbstractClientModule.class), active);
|
||||||
|
}
|
||||||
|
catch (final ClassNotFoundException e) {
|
||||||
|
LOGGER.error("Class not found: " + className, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changeDisplayState(final Class<? extends AbstractClientModule> clazz, final boolean display) {
|
||||||
|
for (final var module : this.modulesAll) {
|
||||||
|
if (module instanceof final AbstractClientModule clientModule && clazz.isAssignableFrom(module.getClass())) {
|
||||||
|
final boolean curDisplayed = this.modulesDisplayed.stream().anyMatch(mod -> clazz.isAssignableFrom(mod.getClass()));
|
||||||
|
|
||||||
|
final boolean doDisplay = display || clientModule.isAlwaysDisplay();
|
||||||
|
if (doDisplay && !curDisplayed) {
|
||||||
|
this.modulesDisplayed.add(clientModule);
|
||||||
|
this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onShow());
|
||||||
|
}
|
||||||
|
else if (!doDisplay && curDisplayed) {
|
||||||
|
this.modulesDisplayed.removeIf(mod -> clazz.isAssignableFrom(mod.getClass()));
|
||||||
|
this.invokeSafe(clientModule, m -> ((AbstractClientModule) m).onHide());
|
||||||
|
}
|
||||||
|
this.modulesDisplayedClientModulesView = List.copyOf(this.modulesDisplayed);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDisplayed(final String className) {
|
||||||
|
try {
|
||||||
|
final var clazz = Class.forName(className);
|
||||||
|
return this.isDisplayed(clazz.asSubclass(AbstractClientModule.class));
|
||||||
|
}
|
||||||
|
catch (final ClassNotFoundException e) {
|
||||||
|
LOGGER.error("Class not found: " + className, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDisplayed(final Class<? extends AbstractClientModule> clazz) {
|
||||||
|
return this.modulesDisplayed.stream().anyMatch(m -> clazz.isAssignableFrom(m.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideAll() {
|
||||||
|
this.lastVisibleStates.clear();
|
||||||
|
|
||||||
|
for (final var module : List.copyOf(this.modulesDisplayed)) {
|
||||||
|
if ((module instanceof final AbstractClientModule clientModule) && !clientModule.isAlwaysDisplay()) {
|
||||||
|
this.changeDisplayState(clientModule.getClass(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SafeVarargs
|
||||||
|
public final void hideExcept(final String... classNames) {
|
||||||
|
final List<AbstractClientModule> state = new ArrayList<>();
|
||||||
|
final var keep = new java.util.HashSet<>(java.util.Arrays.asList(classNames));
|
||||||
|
|
||||||
|
for (final var module : List.copyOf(this.modulesDisplayed)) {
|
||||||
|
if (module instanceof final AbstractClientModule clientModule &&
|
||||||
|
!clientModule.isAlwaysDisplay() &&
|
||||||
|
!keep.contains(clientModule.getClass().getName())) {
|
||||||
|
this.changeDisplayState(clientModule.getClass(), false);
|
||||||
|
state.add(clientModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.isEmpty()) {
|
||||||
|
this.lastVisibleStates.push(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreVisibility() {
|
||||||
|
if (this.lastVisibleStates.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final AbstractClientModule module : this.lastVisibleStates.pop()) {
|
||||||
|
this.changeDisplayState(module.getClass(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isModal() {
|
||||||
|
return !this.lastVisibleStates.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeSafe(final AbstractModule module, final Consumer<AbstractModule> consumer) {
|
||||||
|
try {
|
||||||
|
consumer.accept(module);
|
||||||
|
}
|
||||||
|
catch (final Exception exc) {
|
||||||
|
LOGGER.error("Error in module " + module.getClass().getName(), exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sortModules(final List<AbstractModule> modules) {
|
||||||
|
modules.sort((o1, o2) -> {
|
||||||
|
if (o1 instanceof final AbstractClientModule a1 && o2 instanceof final AbstractClientModule a2) {
|
||||||
|
return Integer.compare(a2.getPriority(), a1.getPriority());
|
||||||
|
}
|
||||||
|
return Boolean.compare(o1 instanceof AbstractClientModule, o2 instanceof AbstractClientModule);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@ de.extio.game_engine.keyboard.KeycodeAutoConfiguration
|
|||||||
de.extio.game_engine.renderer.RendererAutoConfiguration
|
de.extio.game_engine.renderer.RendererAutoConfiguration
|
||||||
de.extio.game_engine.renderer.g2d.G2DAutoConfiguration
|
de.extio.game_engine.renderer.g2d.G2DAutoConfiguration
|
||||||
de.extio.game_engine.storage.StorageServiceAutoConfiguration
|
de.extio.game_engine.storage.StorageServiceAutoConfiguration
|
||||||
|
de.extio.game_engine.module.ModuleManagerAutoConfiguration
|
||||||
|
|||||||
504
src/test/java/de/extio/game_engine/module/ModuleManagerTest.java
Normal file
504
src/test/java/de/extio/game_engine/module/ModuleManagerTest.java
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
package de.extio.game_engine.module;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class ModuleManagerTest {
|
||||||
|
|
||||||
|
private ModuleManagerImpl moduleManager;
|
||||||
|
|
||||||
|
private TestModule testModule;
|
||||||
|
|
||||||
|
private TestClientModule testClientModule;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
this.testModule = new TestModule();
|
||||||
|
this.testClientModule = new TestClientModule();
|
||||||
|
|
||||||
|
final List<AbstractModule> initialModules = new ArrayList<>();
|
||||||
|
initialModules.add(this.testModule);
|
||||||
|
initialModules.add(this.testClientModule);
|
||||||
|
|
||||||
|
this.moduleManager = new ModuleManagerImpl(initialModules);
|
||||||
|
this.moduleManager.afterPropertiesSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAfterPropertiesSet() {
|
||||||
|
assertEquals(2, this.moduleManager.getModulesAll().size());
|
||||||
|
assertTrue(this.testModule.onLoadCalled);
|
||||||
|
assertTrue(this.testClientModule.onLoadCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAfterPropertiesSet_EmptyModules() throws Exception {
|
||||||
|
final ModuleManagerImpl emptyManager = new ModuleManagerImpl(List.of());
|
||||||
|
emptyManager.afterPropertiesSet();
|
||||||
|
|
||||||
|
assertTrue(emptyManager.getModulesAll().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAfterPropertiesSet_NullModules() throws Exception {
|
||||||
|
final ModuleManagerImpl nullManager = new ModuleManagerImpl(null);
|
||||||
|
nullManager.afterPropertiesSet();
|
||||||
|
|
||||||
|
assertTrue(nullManager.getModulesAll().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetModulesAll() {
|
||||||
|
final List<AbstractModule> modules = this.moduleManager.getModulesAll();
|
||||||
|
|
||||||
|
assertEquals(2, modules.size());
|
||||||
|
assertTrue(modules.contains(this.testModule));
|
||||||
|
assertTrue(modules.contains(this.testClientModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetModulesActive_InitiallyEmpty() {
|
||||||
|
assertTrue(this.moduleManager.getModulesActive().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoadModule() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
|
||||||
|
assertEquals(3, this.moduleManager.getModulesAll().size());
|
||||||
|
assertTrue(this.moduleManager.getModulesAll().stream().anyMatch(m -> m instanceof AlwaysDisplayModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoadModule_AlreadyLoaded() {
|
||||||
|
final int initialSize = this.moduleManager.getModulesAll().size();
|
||||||
|
|
||||||
|
this.moduleManager.loadModule(TestModule.class);
|
||||||
|
|
||||||
|
assertEquals(initialSize, this.moduleManager.getModulesAll().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnloadModule() {
|
||||||
|
this.moduleManager.unloadModule(TestModule.class);
|
||||||
|
|
||||||
|
assertEquals(1, this.moduleManager.getModulesAll().size());
|
||||||
|
assertFalse(this.moduleManager.getModulesAll().contains(this.testModule));
|
||||||
|
assertTrue(this.testModule.onUnloadCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnloadModule_NotLoaded() {
|
||||||
|
final int initialSize = this.moduleManager.getModulesAll().size();
|
||||||
|
|
||||||
|
this.moduleManager.unloadModule(AlwaysDisplayModule.class);
|
||||||
|
|
||||||
|
assertEquals(initialSize, this.moduleManager.getModulesAll().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnloadModule_DeactivatesFirst() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
assertTrue(this.moduleManager.getModulesActive().contains(this.testModule));
|
||||||
|
|
||||||
|
this.moduleManager.unloadModule(TestModule.class);
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.getModulesActive().contains(this.testModule));
|
||||||
|
assertTrue(this.testModule.onDeactivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_Activate() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.getModulesActive().contains(this.testModule));
|
||||||
|
assertTrue(this.testModule.onActivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_Deactivate() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
this.testModule.onActivateCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, false);
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.getModulesActive().contains(this.testModule));
|
||||||
|
assertTrue(this.testModule.onDeactivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_AlreadyActive() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
this.testModule.onActivateCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
|
||||||
|
assertFalse(this.testModule.onActivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_AlreadyInactive() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, false);
|
||||||
|
|
||||||
|
assertFalse(this.testModule.onDeactivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_ByClassName() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class.getName(), true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.getModulesActive().contains(this.testModule));
|
||||||
|
assertTrue(this.testModule.onActivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeActiveState_AlwaysDisplayModule() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
|
||||||
|
this.moduleManager.changeActiveState(AlwaysDisplayModule.class, true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(AlwaysDisplayModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeactivateAll() {
|
||||||
|
this.moduleManager.changeActiveState(TestModule.class, true);
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
this.moduleManager.deactivateAll();
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.getModulesActive().isEmpty());
|
||||||
|
assertTrue(this.testModule.onDeactivateCalled);
|
||||||
|
assertTrue(this.testClientModule.onDeactivateCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_Show() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onShowCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onShowCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_Hide() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onHideCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, false);
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onHideCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_AlreadyShown() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onShowCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
assertFalse(this.testClientModule.onShowCalled, "onShow should not be called when already shown");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_AlreadyHidden() {
|
||||||
|
this.testClientModule.onHideCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, false);
|
||||||
|
|
||||||
|
assertFalse(this.testClientModule.onHideCalled, "onHide should not be called when already hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_ByClassName() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onShowCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class.getName(), true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeDisplayState_AlwaysDisplayModule() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
this.moduleManager.changeActiveState(AlwaysDisplayModule.class, true);
|
||||||
|
|
||||||
|
this.moduleManager.changeDisplayState(AlwaysDisplayModule.class, false);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(AlwaysDisplayModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsDisplayed_ByClassName() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(TestClientModule.class.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHideAll() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onHideCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.hideAll();
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onHideCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHideAll_DoesNotHideAlwaysDisplay() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
this.moduleManager.changeActiveState(AlwaysDisplayModule.class, true);
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
this.moduleManager.hideAll();
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(AlwaysDisplayModule.class));
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHideExcept() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeActiveState(AlwaysDisplayModule.class, true);
|
||||||
|
this.testClientModule.onHideCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.hideExcept(AlwaysDisplayModule.class.getName());
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(AlwaysDisplayModule.class));
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onHideCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHideExcept_MultipleExceptions() {
|
||||||
|
this.moduleManager.loadModule(AlwaysDisplayModule.class);
|
||||||
|
this.moduleManager.loadModule(HighPriorityModule.class);
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeActiveState(AlwaysDisplayModule.class, true);
|
||||||
|
this.moduleManager.changeActiveState(HighPriorityModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(HighPriorityModule.class, true);
|
||||||
|
|
||||||
|
this.moduleManager.hideExcept(
|
||||||
|
AlwaysDisplayModule.class.getName(),
|
||||||
|
HighPriorityModule.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(AlwaysDisplayModule.class));
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(HighPriorityModule.class));
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRestoreVisibility() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
|
||||||
|
this.moduleManager.hideExcept();
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
this.testClientModule.onShowCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.restoreVisibility();
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onShowCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRestoreVisibility_NoState() {
|
||||||
|
this.moduleManager.restoreVisibility();
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsModal() {
|
||||||
|
assertFalse(this.moduleManager.isModal());
|
||||||
|
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.hideExcept();
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isModal());
|
||||||
|
|
||||||
|
this.moduleManager.restoreVisibility();
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isModal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testModuleSorting_Priority() {
|
||||||
|
this.moduleManager.loadModule(HighPriorityModule.class);
|
||||||
|
|
||||||
|
final List<AbstractModule> modules = this.moduleManager.getModulesAll();
|
||||||
|
|
||||||
|
assertEquals(3, modules.size());
|
||||||
|
|
||||||
|
int highPriorityIndex = -1;
|
||||||
|
int normalPriorityIndex = -1;
|
||||||
|
int nonClientIndex = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < modules.size(); i++) {
|
||||||
|
if (modules.get(i) instanceof HighPriorityModule) {
|
||||||
|
highPriorityIndex = i;
|
||||||
|
}
|
||||||
|
else if (modules.get(i) instanceof TestClientModule) {
|
||||||
|
normalPriorityIndex = i;
|
||||||
|
}
|
||||||
|
else if (modules.get(i) instanceof TestModule) {
|
||||||
|
nonClientIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(highPriorityIndex >= 0);
|
||||||
|
assertTrue(normalPriorityIndex >= 0);
|
||||||
|
assertTrue(nonClientIndex >= 0);
|
||||||
|
assertTrue(highPriorityIndex < normalPriorityIndex,
|
||||||
|
"High priority (" + highPriorityIndex + ") should come before normal (" + normalPriorityIndex + ")");
|
||||||
|
assertTrue(nonClientIndex < normalPriorityIndex,
|
||||||
|
"Non-client (" + nonClientIndex + ") should come before client (" + normalPriorityIndex + ")");
|
||||||
|
assertTrue(nonClientIndex < highPriorityIndex,
|
||||||
|
"Non-client (" + nonClientIndex + ") should come before high priority client (" + highPriorityIndex + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeactivate_HidesDisplayedClientModule() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.testClientModule.onHideCalled = false;
|
||||||
|
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, false);
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isDisplayed(TestClientModule.class));
|
||||||
|
assertTrue(this.testClientModule.onHideCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeactivateAll_ClearsVisibilityStack() {
|
||||||
|
this.moduleManager.changeActiveState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.changeDisplayState(TestClientModule.class, true);
|
||||||
|
this.moduleManager.hideExcept();
|
||||||
|
|
||||||
|
assertTrue(this.moduleManager.isModal());
|
||||||
|
|
||||||
|
this.moduleManager.deactivateAll();
|
||||||
|
|
||||||
|
assertFalse(this.moduleManager.isModal());
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestModule extends AbstractModule {
|
||||||
|
|
||||||
|
boolean onLoadCalled = false;
|
||||||
|
|
||||||
|
boolean onUnloadCalled = false;
|
||||||
|
|
||||||
|
boolean onActivateCalled = false;
|
||||||
|
|
||||||
|
boolean onDeactivateCalled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
this.onLoadCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnload() {
|
||||||
|
this.onUnloadCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivate() {
|
||||||
|
this.onActivateCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeactivate() {
|
||||||
|
this.onDeactivateCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestClientModule extends AbstractClientModule {
|
||||||
|
|
||||||
|
boolean onLoadCalled = false;
|
||||||
|
|
||||||
|
boolean onUnloadCalled = false;
|
||||||
|
|
||||||
|
boolean onActivateCalled = false;
|
||||||
|
|
||||||
|
boolean onDeactivateCalled = false;
|
||||||
|
|
||||||
|
boolean onShowCalled = false;
|
||||||
|
|
||||||
|
boolean onHideCalled = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
this.onLoadCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnload() {
|
||||||
|
this.onUnloadCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivate() {
|
||||||
|
this.onActivateCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeactivate() {
|
||||||
|
this.onDeactivateCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShow() {
|
||||||
|
this.onShowCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHide() {
|
||||||
|
this.onHideCalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AlwaysDisplayModule extends AbstractClientModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAlwaysDisplay() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class HighPriorityModule extends AbstractClientModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return MODULE_PRIORITY_HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user