// Path: java-modules-context-boot/src/main/java/io/github/tomdw/java/modules/context/boot/api/ModuleContextBooter.java
// public class ModuleContextBooter {
// 
// 	public static void boot() {
// 		ModuleContextRegistry.boot();
// 	}
// 
// 	public static void boot(GenericApplicationContext defaultApplicationContext) {
// 		ModuleContextRegistry.boot(defaultApplicationContext);
// 	}
// 
// 	public static void reset() {
// 		ModuleContextRegistry.reset();
// 	}
// 
// 	public static GenericApplicationContext getContextFor(Module module) {
// 		return ModuleContextRegistry.getContextFor(module);
// 	}
// 
// 	public static void main(String... commandLineArguments) {
// 		ModuleContextBooter.boot();
// 	}
// 
// }
// 
// Path: java-modules-context-boot/src/main/java/io/github/tomdw/java/modules/context/boot/api/ModuleServiceProvider.java
// public class ModuleServiceProvider {
// 
// 	public static <SERVICETYPE> SERVICETYPE provide(Class<SERVICETYPE> servicetypeClass) {
// 		return ModuleContextRegistry.retrieveInstanceFromContext(servicetypeClass);
// 	}
// 
// 	public static <SERVICETYPE> SERVICETYPE provide(Class<SERVICETYPE> servicetypeClass, String serviceName) {
// 		return ModuleContextRegistry.retrieveInstanceFromContext(servicetypeClass, serviceName);
// 	}
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/FailingSpeakerService.java
// public interface FailingSpeakerService {
// 
// 	String getSpeakerNameButThrowsRuntimeException();
// 
// 	String getSpeakerNameButThrowsCheckedException() throws NoSpeakerCheckedException;
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/MultipleSpeakerService.java
// public interface MultipleSpeakerService {
// 	String getName();
// 	void speak(String message);
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/NoSpeakerCheckedException.java
// public class NoSpeakerCheckedException extends Exception {
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/NoSpeakerRuntimeException.java
// public class NoSpeakerRuntimeException extends RuntimeException {
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/SpeakerService.java
// public interface SpeakerService {
// 	String getName();
// 	void speak(String message);
// }


import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.List;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.GenericApplicationContext;
import io.github.tomdw.java.modules.context.boot.api.ModuleContextBooter;
import io.github.tomdw.java.modules.context.boot.api.ModuleServiceProvider;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.FailingSpeakerService;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.MultipleSpeakerService;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.NoSpeakerCheckedException;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.NoSpeakerRuntimeException;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.SpeakerService;
		IntegrationTestService testConfig = IntegrationTestService.getApplicationContext().getBean(IntegrationTestService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getMultipleSpeakerWithGenericsServices()).withFailMessage("No MultipleSpeakerWithGenericsService(s) injected").isNotNull();
		assertThat(testConfig.getMultipleSpeakerWithGenericsServices().get(0).getMultipleSpeakerName()).asString().isEqualTo("myMultipleGenericSpeakerName");
	}

	@Test
	public void singleServiceFromOtherModuleCanBeInjectedUsingModuleServiceReferenceOnConstructorParameter() {
		ModuleContextBooter.main();

		IntegrationTestUsingConstructorInjectionService testConfig = IntegrationTestUsingConstructorInjectionService.getApplicationContext().getBean(IntegrationTestUsingConstructorInjectionService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getSpeakerService()).withFailMessage("No SpeakerService injected").isNotNull();
		assertThat(testConfig.getSpeakerService().getName()).withFailMessage("Wrong SpeakerService injected").isEqualTo("Default");
	}

	@Test
	public void serviceListFromOtherModuleCanBeInjectedUsingModuleServiceReferenceOnConstructorParameter() {
		ModuleContextBooter.main();

		IntegrationTestUsingConstructorInjectionService testConfig = IntegrationTestService.getApplicationContext().getBean(IntegrationTestUsingConstructorInjectionService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getMultipleSpeakerServices()).withFailMessage("No MultipleSpeakerService(s) injected").isNotNull();
		assertThat(testConfig.getMultipleSpeakerServices().stream().map(MultipleSpeakerService::getName)).containsExactlyInAnyOrder("Default", "Other");
	}

	@Test
// Path: java-modules-context-boot/src/main/java/io/github/tomdw/java/modules/context/boot/api/ModuleContextBooter.java
// public class ModuleContextBooter {
// 
// 	public static void boot() {
// 		ModuleContextRegistry.boot();
// 	}
// 
// 	public static void boot(GenericApplicationContext defaultApplicationContext) {
// 		ModuleContextRegistry.boot(defaultApplicationContext);
// 	}
// 
// 	public static void reset() {
// 		ModuleContextRegistry.reset();
// 	}
// 
// 	public static GenericApplicationContext getContextFor(Module module) {
// 		return ModuleContextRegistry.getContextFor(module);
// 	}
// 
// 	public static void main(String... commandLineArguments) {
// 		ModuleContextBooter.boot();
// 	}
// 
// }
// 
// Path: java-modules-context-boot/src/main/java/io/github/tomdw/java/modules/context/boot/api/ModuleServiceProvider.java
// public class ModuleServiceProvider {
// 
// 	public static <SERVICETYPE> SERVICETYPE provide(Class<SERVICETYPE> servicetypeClass) {
// 		return ModuleContextRegistry.retrieveInstanceFromContext(servicetypeClass);
// 	}
// 
// 	public static <SERVICETYPE> SERVICETYPE provide(Class<SERVICETYPE> servicetypeClass, String serviceName) {
// 		return ModuleContextRegistry.retrieveInstanceFromContext(servicetypeClass, serviceName);
// 	}
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/FailingSpeakerService.java
// public interface FailingSpeakerService {
// 
// 	String getSpeakerNameButThrowsRuntimeException();
// 
// 	String getSpeakerNameButThrowsCheckedException() throws NoSpeakerCheckedException;
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/MultipleSpeakerService.java
// public interface MultipleSpeakerService {
// 	String getName();
// 	void speak(String message);
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/NoSpeakerCheckedException.java
// public class NoSpeakerCheckedException extends Exception {
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/NoSpeakerRuntimeException.java
// public class NoSpeakerRuntimeException extends RuntimeException {
// }
// 
// Path: samples/basicapplication/speaker/src/main/java/io/github/tomdw/java/modules/spring/samples/basicapplication/speaker/api/SpeakerService.java
// public interface SpeakerService {
// 	String getName();
// 	void speak(String message);
// }


// Path: integration-tests/src/test/java/io/github/tomdw/java/modules/spring/integration/tests/JavaModulesSpringContextBootIntegrationTest.java
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.List;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.GenericApplicationContext;
import io.github.tomdw.java.modules.context.boot.api.ModuleContextBooter;
import io.github.tomdw.java.modules.context.boot.api.ModuleServiceProvider;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.FailingSpeakerService;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.MultipleSpeakerService;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.NoSpeakerCheckedException;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.NoSpeakerRuntimeException;
import io.github.tomdw.java.modules.spring.samples.basicapplication.speaker.api.SpeakerService;

		IntegrationTestService testConfig = IntegrationTestService.getApplicationContext().getBean(IntegrationTestService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getMultipleSpeakerWithGenericsServices()).withFailMessage("No MultipleSpeakerWithGenericsService(s) injected").isNotNull();
		assertThat(testConfig.getMultipleSpeakerWithGenericsServices().get(0).getMultipleSpeakerName()).asString().isEqualTo("myMultipleGenericSpeakerName");
	}

	@Test
	public void singleServiceFromOtherModuleCanBeInjectedUsingModuleServiceReferenceOnConstructorParameter() {
		ModuleContextBooter.main();

		IntegrationTestUsingConstructorInjectionService testConfig = IntegrationTestUsingConstructorInjectionService.getApplicationContext().getBean(IntegrationTestUsingConstructorInjectionService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getSpeakerService()).withFailMessage("No SpeakerService injected").isNotNull();
		assertThat(testConfig.getSpeakerService().getName()).withFailMessage("Wrong SpeakerService injected").isEqualTo("Default");
	}

	@Test
	public void serviceListFromOtherModuleCanBeInjectedUsingModuleServiceReferenceOnConstructorParameter() {
		ModuleContextBooter.main();

		IntegrationTestUsingConstructorInjectionService testConfig = IntegrationTestService.getApplicationContext().getBean(IntegrationTestUsingConstructorInjectionService.class);
		assertThat(testConfig).isNotNull();

		assertThat(testConfig.getMultipleSpeakerServices()).withFailMessage("No MultipleSpeakerService(s) injected").isNotNull();
		assertThat(testConfig.getMultipleSpeakerServices().stream().map(MultipleSpeakerService::getName)).containsExactlyInAnyOrder("Default", "Other");
	}

	@Test
	public void singleServiceFromOtherModuleCanBeRetrievedSpecificallyOnBeanNameOnConstructorParameter() {