/app/controllers/GraphAlgorithmController.java

https://gitlab.com/flytosky/climate-service-backend · Java · 222 lines · 192 code · 27 blank · 3 comment · 36 complexity · 3e7ede5455c9fd6dc5d099dd11b57244 MD5 · raw file

  1. package controllers;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import javax.inject.Inject;
  7. import javax.inject.Named;
  8. import javax.inject.Singleton;
  9. import org.jgrapht.GraphPath;
  10. import org.jgrapht.WeightedGraph;
  11. import org.jgrapht.alg.DijkstraShortestPath;
  12. import org.jgrapht.alg.KShortestPaths;
  13. import org.jgrapht.graph.DefaultWeightedEdge;
  14. import org.jgrapht.graph.SimpleWeightedGraph;
  15. import models.ClimateService;
  16. import models.ClimateServiceRepository;
  17. import models.Dataset;
  18. import models.DatasetAndUser;
  19. import models.DatasetAndUserRepository;
  20. import models.DatasetRepository;
  21. import models.ServiceAndDataset;
  22. import models.ServiceAndDatasetRepository;
  23. import models.ServiceAndUser;
  24. import models.ServiceAndUserRepository;
  25. import models.User;
  26. import models.UserRepository;
  27. import play.mvc.Controller;
  28. import play.mvc.Result;
  29. import util.HashMapUtil;
  30. import util.Matrix;
  31. import com.fasterxml.jackson.databind.JsonNode;
  32. import com.google.gson.Gson;
  33. @Named
  34. @Singleton
  35. public class GraphAlgorithmController extends Controller {
  36. private final DatasetAndUserRepository datasetAndUserRepository;
  37. private final ServiceAndUserRepository serviceAndUserRepository;
  38. private final ServiceAndDatasetRepository serviceAndDatasetRepository;
  39. private final UserRepository userRepository;
  40. private final DatasetRepository datasetRepository;
  41. private final ClimateServiceRepository serviceRepository;
  42. @Inject
  43. public GraphAlgorithmController(
  44. DatasetAndUserRepository datasetAndUserRepository,
  45. ServiceAndUserRepository serviceAndUserRepository,
  46. ServiceAndDatasetRepository serviceAndDatasetRepository,
  47. UserRepository userRepository, DatasetRepository datasetRepository,
  48. ClimateServiceRepository serviceRepository) {
  49. this.datasetAndUserRepository = datasetAndUserRepository;
  50. this.serviceAndUserRepository = serviceAndUserRepository;
  51. this.serviceAndDatasetRepository = serviceAndDatasetRepository;
  52. this.userRepository = userRepository;
  53. this.datasetRepository = datasetRepository;
  54. this.serviceRepository = serviceRepository;
  55. }
  56. public Result getShortestPath(int source, int target, String format) {
  57. try {
  58. Iterable<DatasetAndUser> userDatasets = datasetAndUserRepository
  59. .findAll();
  60. if (userDatasets == null) {
  61. System.out.println("User and Dataset: cannot be found!");
  62. return notFound("User and Dataset: cannot be found!");
  63. }
  64. List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
  65. List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
  66. WeightedGraph<Integer, DefaultWeightedEdge> graph = createGraph(userDatasets, nodes, rels);
  67. Map<String, Object> map = new HashMap<>();
  68. List<Map<String, Object>> node = new ArrayList<Map<String, Object>>();
  69. List<Map<String, Object>> rel = new ArrayList<Map<String, Object>>();
  70. List<DefaultWeightedEdge> path =
  71. DijkstraShortestPath.findPathBetween(graph, source, target);
  72. for(DefaultWeightedEdge p : path) {
  73. int v1 = graph.getEdgeSource(p);
  74. int v2 = graph.getEdgeTarget(p);
  75. if(!node.contains(nodes.get(v1-1)))
  76. node.add(nodes.get(v1-1));
  77. if(!node.contains(nodes.get(v2-1)))
  78. node.add(nodes.get(v2-1));
  79. for(Map<String, Object> one : rels) {
  80. if((int)one.get("from") == v1 && (int)one.get("to") == v2) {
  81. rel.add(one);
  82. }
  83. }
  84. }
  85. map = HashMapUtil.map("nodes", node, "edges", rel);
  86. String result = new String();
  87. if (format.equals("json")) {
  88. result = new Gson().toJson(map);
  89. }
  90. return ok(result);
  91. } catch (Exception e) {
  92. return badRequest(e.getMessage());
  93. }
  94. }
  95. public Result getKShortestPath(int source, int target, int k, String format) {
  96. try {
  97. Iterable<DatasetAndUser> userDatasets = datasetAndUserRepository
  98. .findAll();
  99. if (userDatasets == null) {
  100. System.out.println("User and Dataset: cannot be found!");
  101. return notFound("User and Dataset: cannot be found!");
  102. }
  103. List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
  104. List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
  105. WeightedGraph<Integer, DefaultWeightedEdge> graph = createGraph(userDatasets, nodes, rels);
  106. // return this map list
  107. List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
  108. KShortestPaths kPaths = new KShortestPaths(graph, source, k);
  109. List<GraphPath> paths = kPaths.getPaths(target);
  110. for(GraphPath p : paths) {
  111. List<Map<String, Object>> node = new ArrayList<Map<String, Object>>();
  112. List<Map<String, Object>> rel = new ArrayList<Map<String, Object>>();
  113. for (Object edge : p.getEdgeList()) {
  114. int v1 = graph.getEdgeSource((DefaultWeightedEdge)edge);
  115. int v2 = graph.getEdgeTarget((DefaultWeightedEdge)edge);
  116. if(!node.contains(nodes.get(v1-1)))
  117. node.add(nodes.get(v1-1));
  118. if(!node.contains(nodes.get(v2-1)))
  119. node.add(nodes.get(v2-1));
  120. for (Map<String, Object> one : rels) {
  121. if((int)one.get("from") == v1 && (int)one.get("to") == v2) {
  122. rel.add(one);
  123. }
  124. }
  125. }
  126. mapList.add(HashMapUtil.map("nodes", node, "edges", rel));
  127. }
  128. String result = new String();
  129. if (format.equals("json")) {
  130. result = new Gson().toJson(mapList);
  131. }
  132. return ok(result);
  133. } catch (Exception e) {
  134. return badRequest(e.getMessage());
  135. }
  136. }
  137. public WeightedGraph<Integer, DefaultWeightedEdge> createGraph(Iterable<DatasetAndUser> userDatasets,
  138. List<Map<String, Object>> nodes, List<Map<String, Object>> rels) {
  139. WeightedGraph<Integer, DefaultWeightedEdge> g =
  140. new SimpleWeightedGraph<Integer, DefaultWeightedEdge>(DefaultWeightedEdge.class);
  141. int i = 1;
  142. long edgeId = 1;
  143. for (DatasetAndUser userDataset : userDatasets) {
  144. int source = 0;
  145. int target = 0;
  146. // Check whether the current user has already existed
  147. for (int j = 0; j < nodes.size(); j++) {
  148. if (nodes.get(j).get("group").equals("user")
  149. && (long) nodes.get(j).get("userId") == userDataset
  150. .getUser().getId()) {
  151. source = (int) nodes.get(j).get("id");
  152. nodes.get(j).put("value", (int)nodes.get(j).get("value") + 1);
  153. break;
  154. }
  155. }
  156. if (source == 0) {
  157. String realName = userDataset.getUser().getFirstName() + " "
  158. + userDataset.getUser().getLastName();
  159. nodes.add(HashMapUtil.map7("id", i, "title", realName, "label", userDataset
  160. .getUser().getUserName(), "cluster", "1", "value", 1,
  161. "group", "user", "userId", userDataset.getUser()
  162. .getId()));
  163. source = i;
  164. g.addVertex(source);
  165. i++;
  166. }
  167. // Check whether the current dataset has already existed
  168. for (int j = 0; j < nodes.size(); j++) {
  169. if (nodes.get(j).get("group").equals("dataset")
  170. && (long) nodes.get(j).get("datasetId") == userDataset
  171. .getDataset().getId()) {
  172. target = (int) nodes.get(j).get("id");
  173. nodes.get(j).put("value", (int)nodes.get(j).get("value") + 1);
  174. break;
  175. }
  176. }
  177. if (target == 0) {
  178. nodes.add(HashMapUtil.map7("id", i, "title", userDataset.getDataset()
  179. .getName(), "label",
  180. userDataset.getDataset().getName(), "cluster", "2",
  181. "value", 25, "group", "dataset", "datasetId",
  182. userDataset.getDataset().getId()));
  183. target = i;
  184. g.addVertex(target);
  185. i++;
  186. }
  187. rels.add(HashMapUtil.map5("from", source, "to", target, "title", "USE",
  188. "id", edgeId, "weight", userDataset.getCount()));
  189. g.addEdge(source, target);
  190. g.setEdgeWeight(g.getEdge(source, target), userDataset.getCount());
  191. edgeId++;
  192. }
  193. return g;
  194. }
  195. }