package com.github.aesteve.vertx.nubes.fixtures;
import com.github.aesteve.vertx.nubes.Config;
import com.github.aesteve.vertx.nubes.services.ServiceRegistry;
import com.github.aesteve.vertx.nubes.utils.async.AsyncUtils;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import org.reflections.Reflections;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FixtureLoader {
private final Vertx vertx;
private final Config config;
private final ServiceRegistry serviceRegistry;
private final Set<Fixture> fixtures;
public FixtureLoader(Vertx vertx, Config config, ServiceRegistry serviceRegistry) {
this.vertx = vertx;
this.config = config;
this.serviceRegistry = serviceRegistry;
fixtures = new HashSet<>();
}
public void setUp(Future<Void> future) {
instanciateFixtures(future);
if (future.failed()) {
return;
}
exec(future, "startUp");
}
public void tearDown(Future<Void> future) {
exec(future, "tearDown");
}
private void exec(Future<Void> rootFuture, String methodName) {
if (fixtures.isEmpty()) {
rootFuture.complete();
return;
}
List<Handler<Future<Void>>> list = new ArrayList<>();
fixtures.stream().sorted().forEach(fixture -> {
switch (methodName) {
case "startUp":
list.add(fut -> fixture.startUp(vertx, fut));
break;
case "tearDown":
list.add(fut -> fixture.tearDown(vertx, fut));
break;
default:
throw new IllegalArgumentException("Unknown method : " + methodName);
}
});
AsyncUtils.chainHandlers(rootFuture, list);
}
private void injectServicesIntoFixture(Fixture fixture) throws IllegalAccessException {
for (Field field : fixture.getClass().getDeclaredFields()) {
Object service = serviceRegistry.get(field);
if (service != null) {
field.setAccessible(true);
field.set(fixture, service);
}
}
}
private void instanciateFixtures(Future<Void> future) {
List<String> fixturePackages = config.getFixturePackages();
if (fixturePackages == null || fixturePackages.isEmpty()) {
return;
}
for (String fixturePackage : fixturePackages) {
Reflections reflections = new Reflections(fixturePackage);
Set<Class<? extends Fixture>> fixtureClasses = reflections.getSubTypesOf(Fixture.class);
for (Class<? extends Fixture> fixtureClass : fixtureClasses) {
try {
Fixture fixture = fixtureClass.newInstance();
injectServicesIntoFixture(fixture);
fixtures.add(fixture);
} catch (Exception e) {
future.fail(e);
return;
}
}
}
}
}