129 lines
5.1 KiB
Java
129 lines
5.1 KiB
Java
package org.insa.algo;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.util.IdentityHashMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
|
|
import org.insa.algo.shortestpath.AStarAlgorithm;
|
|
import org.insa.algo.shortestpath.BellmanFordAlgorithm;
|
|
import org.insa.algo.shortestpath.DijkstraAlgorithm;
|
|
import org.insa.algo.shortestpath.ShortestPathAlgorithm;
|
|
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
|
|
|
|
/**
|
|
* Factory class used to register and retrieve algorithms based on their common
|
|
* ancestor and name.
|
|
*
|
|
*/
|
|
public class AlgorithmFactory {
|
|
|
|
// Map between algorithm names and class.
|
|
private final static Map<Class<? extends AbstractAlgorithm<?>>, Map<String, Class<? extends AbstractAlgorithm<?>>>> ALGORITHMS = new IdentityHashMap<>();
|
|
|
|
static {
|
|
// Register weakly-connected components algorithm:
|
|
registerAlgorithm(WeaklyConnectedComponentsAlgorithm.class, "WCC basic",
|
|
WeaklyConnectedComponentsAlgorithm.class);
|
|
|
|
// Register shortest path algorithm:
|
|
registerAlgorithm(ShortestPathAlgorithm.class, "Bellman-Ford", BellmanFordAlgorithm.class);
|
|
registerAlgorithm(ShortestPathAlgorithm.class, "Dijkstra", DijkstraAlgorithm.class);
|
|
registerAlgorithm(ShortestPathAlgorithm.class, "A*", AStarAlgorithm.class);
|
|
|
|
// Register your algorithms here:
|
|
// registerAlgorithm(CarPoolingAlgorithm.class, "My Awesome Algorithm",
|
|
// MyCarPoolingAlgorithm.class);
|
|
}
|
|
|
|
/**
|
|
* Register the given algorithm class with the given name as a child class of
|
|
* the given base algorithm.
|
|
*
|
|
* @param baseAlgorithm Base algorithm class that corresponds to the newly
|
|
* registered algorithm class (e.g., generic algorithm class for the
|
|
* problem).
|
|
* @param name Name for the registered algorithm class.
|
|
* @param algoClass Algorithm class to register.
|
|
*/
|
|
public static void registerAlgorithm(Class<? extends AbstractAlgorithm<?>> baseAlgorithm,
|
|
String name, Class<? extends AbstractAlgorithm<?>> algoClass) {
|
|
if (!ALGORITHMS.containsKey(baseAlgorithm)) {
|
|
ALGORITHMS.put(baseAlgorithm, new LinkedHashMap<>());
|
|
}
|
|
ALGORITHMS.get(baseAlgorithm).put(name, algoClass);
|
|
}
|
|
|
|
/**
|
|
* Create an instance of the given algorithm class using the given input data.
|
|
* Assuming algorithm correspond to a class "Algorithm", this function returns
|
|
* an object equivalent to `new Algorithm(data)`.
|
|
*
|
|
* @param algorithm Class of the algorithm to create.
|
|
* @param data Input data for the algorithm.
|
|
*
|
|
* @return A new instance of the given algorithm class using the given data.
|
|
*
|
|
* @throws Exception if something wrong happens when constructing the object,
|
|
* i.e. the given input data does not correspond to the given algorithm
|
|
* and/or no constructor that takes a single parameter of type
|
|
* (data.getClass()) exists.
|
|
*/
|
|
public static AbstractAlgorithm<?> createAlgorithm(
|
|
Class<? extends AbstractAlgorithm<?>> algorithm, AbstractInputData data)
|
|
throws Exception {
|
|
// Retrieve the set of constructors for the given algorithm class.
|
|
Constructor<?>[] constructors = algorithm.getDeclaredConstructors();
|
|
|
|
// Within this set, find the constructor that can be called with "data" (only).
|
|
AbstractAlgorithm<?> constructed = null;
|
|
for (Constructor<?> c: constructors) {
|
|
Class<?>[] params = c.getParameterTypes();
|
|
if (params.length == 1 && params[0].isAssignableFrom(data.getClass())) {
|
|
c.setAccessible(true);
|
|
constructed = (AbstractAlgorithm<?>) c.newInstance(new Object[]{ data });
|
|
break;
|
|
}
|
|
}
|
|
return constructed;
|
|
}
|
|
|
|
/**
|
|
* Return the algorithm class corresponding to the given base algorithm class
|
|
* and name. The algorithm must have been previously registered using
|
|
* registerAlgorithm.
|
|
*
|
|
* @param baseAlgorithm Base algorithm class for the algorithm to retrieve.
|
|
* @param name Name of the algorithm to retrieve.
|
|
*
|
|
* @return Class corresponding to the given name.
|
|
*
|
|
* @see #registerAlgorithm
|
|
*/
|
|
public static Class<? extends AbstractAlgorithm<?>> getAlgorithmClass(
|
|
Class<? extends AbstractAlgorithm<?>> baseAlgorithm, String name) {
|
|
return ALGORITHMS.get(baseAlgorithm).get(name);
|
|
}
|
|
|
|
/**
|
|
* Return the list of names corresponding to the registered algorithm classes
|
|
* for the given base algorithm class.
|
|
*
|
|
* @param baseAlgorithm Base algorithm class for the algorithm class names to
|
|
* retrieve.
|
|
*
|
|
* @return Names of the currently registered algorithms.
|
|
*
|
|
* @see #registerAlgorithm
|
|
*/
|
|
public static Set<String> getAlgorithmNames(
|
|
Class<? extends AbstractAlgorithm<?>> baseAlgorithm) {
|
|
if (!ALGORITHMS.containsKey(baseAlgorithm)) {
|
|
return new TreeSet<>();
|
|
}
|
|
return ALGORITHMS.get(baseAlgorithm).keySet();
|
|
}
|
|
}
|