
es.urjc.etsii.grafo.services.ReflectiveSolutionBuilder Maven / Gradle / Ivy
package es.urjc.etsii.grafo.services;
import es.urjc.etsii.grafo.create.builder.SolutionBuilder;
import es.urjc.etsii.grafo.io.Instance;
import es.urjc.etsii.grafo.solution.Solution;
import es.urjc.etsii.grafo.testutil.TestSolution;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;
/**
* ReflectiveSolutionBuilder class.
*/
@SuppressWarnings("unchecked")
public class ReflectiveSolutionBuilder, I extends Instance> extends SolutionBuilder {
private final Class solClass;
private Constructor constructor;
/**
* Constructor for ReflectiveSolutionBuilder.
*/
public ReflectiveSolutionBuilder() {
Set> set = findSolutionCandidates(getPkgsToScan());
if (set.isEmpty()) {
throw new RuntimeException("Cannot find any class extending Solution");
}
if (set.size() > 1) {
throw new RuntimeException(String.format("Found multiple classes extending Solution (%s), provide only one or extend the class SolutionBuilder and implement the required method", set));
}
solClass = set.iterator().next();
}
/**
* {@inheritDoc}
*/
@Override
public S initializeSolution(I instance) {
if (constructor == null) {
initializeConstructorReference(instance);
}
try {
var solution = constructor.newInstance(instance);
return solution;
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* Get correct constructor reference and cache it.
* This method can be called by several threads at the same time
*
* @param i Instance class, get constructor by correct type
*/
private synchronized void initializeConstructorReference(I i) {
if (constructor != null) return;
try {
constructor = this.solClass.getConstructor(i.getClass());
} catch (NoSuchMethodException e) {
throw new RuntimeException("Could not found Solution constructor Solution(Instance)");
}
}
private String[] getPkgsToScan() {
var pkgs = System.getProperty("advanced.scan-pkgs", "es.urjc.etsii");
return pkgs.split(",");
}
private Set> findSolutionCandidates(String[] pkgs) {
var provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(Solution.class));
Set allComponentes = new HashSet<>();
for (var pkg : pkgs) {
allComponentes.addAll(provider.findCandidateComponents(pkg.replace(".", "/")));
}
Set> solutionImplementations = new HashSet<>();
for (BeanDefinition component : allComponentes) {
try {
Class cls = (Class) Class.forName(component.getBeanClassName());
if (!TestSolution.class.isAssignableFrom(cls)) {
// Skip test implementations
solutionImplementations.add(cls);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
return solutionImplementations;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy