No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AlgorithmFactory.java 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package org.insa.graphs.algorithm;
  2. import java.lang.reflect.Constructor;
  3. import java.util.IdentityHashMap;
  4. import java.util.LinkedHashMap;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.TreeSet;
  8. import org.insa.graphs.algorithm.shortestpath.AStarAlgorithm;
  9. import org.insa.graphs.algorithm.shortestpath.BellmanFordAlgorithm;
  10. import org.insa.graphs.algorithm.shortestpath.DijkstraAlgorithm;
  11. import org.insa.graphs.algorithm.shortestpath.ShortestPathAlgorithm;
  12. import org.insa.graphs.algorithm.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
  13. /**
  14. * Factory class used to register and retrieve algorithms based on their common
  15. * ancestor and name.
  16. *
  17. */
  18. public class AlgorithmFactory {
  19. // Map between algorithm names and class.
  20. private final static Map<Class<? extends AbstractAlgorithm<?>>, Map<String, Class<? extends AbstractAlgorithm<?>>>> ALGORITHMS = new IdentityHashMap<>();
  21. static {
  22. // Register weakly-connected components algorithm:
  23. registerAlgorithm(WeaklyConnectedComponentsAlgorithm.class, "WCC basic",
  24. WeaklyConnectedComponentsAlgorithm.class);
  25. // Register shortest path algorithm:
  26. registerAlgorithm(ShortestPathAlgorithm.class, "Bellman-Ford", BellmanFordAlgorithm.class);
  27. registerAlgorithm(ShortestPathAlgorithm.class, "Dijkstra", DijkstraAlgorithm.class);
  28. registerAlgorithm(ShortestPathAlgorithm.class, "A*", AStarAlgorithm.class);
  29. // Register your algorithms here:
  30. // registerAlgorithm(CarPoolingAlgorithm.class, "My Awesome Algorithm",
  31. // MyCarPoolingAlgorithm.class);
  32. }
  33. /**
  34. * Register the given algorithm class with the given name as a child class of
  35. * the given base algorithm.
  36. *
  37. * @param baseAlgorithm Base algorithm class that corresponds to the newly
  38. * registered algorithm class (e.g., generic algorithm
  39. * class for the problem).
  40. * @param name Name for the registered algorithm class.
  41. * @param algoClass Algorithm class to register.
  42. */
  43. public static void registerAlgorithm(Class<? extends AbstractAlgorithm<?>> baseAlgorithm,
  44. String name, Class<? extends AbstractAlgorithm<?>> algoClass) {
  45. if (!ALGORITHMS.containsKey(baseAlgorithm)) {
  46. ALGORITHMS.put(baseAlgorithm, new LinkedHashMap<>());
  47. }
  48. ALGORITHMS.get(baseAlgorithm).put(name, algoClass);
  49. }
  50. /**
  51. * Create an instance of the given algorithm class using the given input data.
  52. * Assuming algorithm correspond to a class "Algorithm", this function returns
  53. * an object equivalent to `new Algorithm(data)`.
  54. *
  55. * @param algorithm Class of the algorithm to create.
  56. * @param data Input data for the algorithm.
  57. *
  58. * @return A new instance of the given algorithm class using the given data.
  59. *
  60. * @throws Exception if something wrong happens when constructing the object,
  61. * i.e. the given input data does not correspond to the given
  62. * algorithm and/or no constructor that takes a single
  63. * parameter of type (data.getClass()) exists.
  64. */
  65. public static AbstractAlgorithm<?> createAlgorithm(
  66. Class<? extends AbstractAlgorithm<?>> algorithm, AbstractInputData data)
  67. throws Exception {
  68. // Retrieve the set of constructors for the given algorithm class.
  69. Constructor<?>[] constructors = algorithm.getDeclaredConstructors();
  70. // Within this set, find the constructor that can be called with "data" (only).
  71. AbstractAlgorithm<?> constructed = null;
  72. for (Constructor<?> c: constructors) {
  73. Class<?>[] params = c.getParameterTypes();
  74. if (params.length == 1 && params[0].isAssignableFrom(data.getClass())) {
  75. c.setAccessible(true);
  76. constructed = (AbstractAlgorithm<?>) c.newInstance(new Object[] { data });
  77. break;
  78. }
  79. }
  80. return constructed;
  81. }
  82. /**
  83. * Return the algorithm class corresponding to the given base algorithm class
  84. * and name. The algorithm must have been previously registered using
  85. * registerAlgorithm.
  86. *
  87. * @param baseAlgorithm Base algorithm class for the algorithm to retrieve.
  88. * @param name Name of the algorithm to retrieve.
  89. *
  90. * @return Class corresponding to the given name.
  91. *
  92. * @see #registerAlgorithm
  93. */
  94. public static Class<? extends AbstractAlgorithm<?>> getAlgorithmClass(
  95. Class<? extends AbstractAlgorithm<?>> baseAlgorithm, String name) {
  96. return ALGORITHMS.get(baseAlgorithm).get(name);
  97. }
  98. /**
  99. * Return the list of names corresponding to the registered algorithm classes
  100. * for the given base algorithm class.
  101. *
  102. * @param baseAlgorithm Base algorithm class for the algorithm class names to
  103. * retrieve.
  104. *
  105. * @return Names of the currently registered algorithms.
  106. *
  107. * @see #registerAlgorithm
  108. */
  109. public static Set<String> getAlgorithmNames(
  110. Class<? extends AbstractAlgorithm<?>> baseAlgorithm) {
  111. if (!ALGORITHMS.containsKey(baseAlgorithm)) {
  112. return new TreeSet<>();
  113. }
  114. return ALGORITHMS.get(baseAlgorithm).keySet();
  115. }
  116. }