update backend: Add Relational Knowledge Graph APIs and modified data models
diff --git a/ApacheCMDA_Backend_1.0/.DS_Store b/ApacheCMDA_Backend_1.0/.DS_Store
index 5495852..d540f2b 100644
--- a/ApacheCMDA_Backend_1.0/.DS_Store
+++ b/ApacheCMDA_Backend_1.0/.DS_Store
Binary files differ
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java b/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java
index feed694..f5f44d4 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java
@@ -9,33 +9,307 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import models.ClimateService;
+import models.ClimateServiceRepository;
+import models.Dataset;
import models.DatasetAndUser;
import models.DatasetAndUserRepository;
+import models.DatasetRepository;
+import models.ServiceAndDataset;
+import models.ServiceAndDatasetRepository;
+import models.ServiceAndUser;
+import models.ServiceAndUserRepository;
+import models.User;
+import models.UserRepository;
import play.mvc.Controller;
import play.mvc.Result;
+import util.Matrix;
+import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.Gson;
@Named
@Singleton
-public class AnalyticsController extends Controller{
+public class AnalyticsController extends Controller {
+
private final DatasetAndUserRepository datasetAndUserRepository;
+ private final ServiceAndUserRepository serviceAndUserRepository;
+ private final ServiceAndDatasetRepository serviceAndDatasetRepository;
+ private final UserRepository userRepository;
+ private final DatasetRepository datasetRepository;
+ private final ClimateServiceRepository serviceRepository;
+
@Inject
- public AnalyticsController(DatasetAndUserRepository datasetAndUserRepository) {
+ public AnalyticsController(
+ DatasetAndUserRepository datasetAndUserRepository,
+ ServiceAndUserRepository serviceAndUserRepository,
+ ServiceAndDatasetRepository serviceAndDatasetRepository,
+ UserRepository userRepository, DatasetRepository datasetRepository,
+ ClimateServiceRepository serviceRepository) {
this.datasetAndUserRepository = datasetAndUserRepository;
+ this.serviceAndUserRepository = serviceAndUserRepository;
+ this.serviceAndDatasetRepository = serviceAndDatasetRepository;
+ this.userRepository = userRepository;
+ this.datasetRepository = datasetRepository;
+ this.serviceRepository = serviceRepository;
+ }
+
+ public long getResultCount(String param) {
+ long count = 0;
+ switch (param) {
+ case "User":
+ count = userRepository.count();
+ break;
+ case "Dataset":
+ count = datasetRepository.count();
+ break;
+ case "Service":
+ count = serviceRepository.count();
+ break;
+ default:
+ break;
+ }
+ return count;
}
- public Result getAllDatasetAndUserWithCount(String format) {
+ public Map<String, Object> generateRelationalMap(String param1, String param2, String param3) {
+ String option = param1 + param2 + param3;
+ Map<String, Object> map = new HashMap<>();
+ int[][] relations = null;
+ int count1 = (int) getResultCount(param1), count3 = (int) getResultCount(param3);
+
+ switch (option) {
+ case "UserUserDataset": {
+ relations = new int[count1][count3];
+ Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+ .findAll();
+
+ if (datasetAndUsers == null) {
+ System.out.println("User and Dataset: cannot be found!");
+ }
+
+ for (DatasetAndUser one : datasetAndUsers) {
+ int i = (int) one.getUser().getId() - 1;
+ int j = (int) one.getDataset().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "user");
+ break;
+ }
+ case "UserUserService": {
+ relations = new int[count1][count3];
+ Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+ .findAll();
+
+ if (serviceAndUsers == null) {
+ System.out.println("User and Service: cannot be found!");
+ }
+
+ for (ServiceAndUser one : serviceAndUsers) {
+ int i = (int) one.getUser().getId() - 1;
+ int j = (int) one.getClimateService().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "user");
+ break;
+ }
+ case "DatasetDatasetUser": {
+ relations = new int[count1][count3];
+ Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+ .findAll();
+
+ if (datasetAndUsers == null) {
+ System.out.println("User and Dataset: cannot be found!");
+ }
+
+ for (DatasetAndUser one : datasetAndUsers) {
+ int i = (int) one.getDataset().getId() - 1;
+ int j = (int) one.getUser().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "dataset");
+ break;
+ }
+ case "DatasetDatasetService": {
+ relations = new int[count1][count3];
+ Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+ .findAll();
+
+ if (datasetAndServices == null) {
+ System.out.println("Dataset and Service: cannot be found!");
+ }
+
+ for (ServiceAndDataset one : datasetAndServices) {
+ int i = (int) one.getDataset().getId() - 1;
+ int j = (int) one.getClimateService().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "dataset");
+ break;
+ }
+ case "ServiceServiceUser": {
+ relations = new int[count1][count3];
+ Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+ .findAll();
+
+ if (serviceAndUsers == null) {
+ System.out.println("User and Service: cannot be found!");
+ }
+
+ for (ServiceAndUser one : serviceAndUsers) {
+ int i = (int) one.getClimateService().getId() - 1;
+ int j = (int) one.getUser().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "service");
+ break;
+ }
+ case "ServiceServiceDataset": {
+ relations = new int[count1][count3];
+ Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+ .findAll();
+
+ if (datasetAndServices == null) {
+ System.out.println("Dataset and Service: cannot be found!");
+ }
+
+ for (ServiceAndDataset one : datasetAndServices) {
+ int i = (int) one.getClimateService().getId() - 1;
+ int j = (int) one.getDataset().getId() - 1;
+ relations[i][j] = (int) one.getCount();
+ }
+
+ Matrix m1 = new Matrix(relations);
+ Matrix m2 = m1.transpose();
+ Matrix m3 = m1.times(m2);
+ int[][] res = m3.getArray();
+
+ map = jsonFormatForMatrix(res, "service");
+ break;
+ }
+ case "UserDatasetService":
+ map = getAllDatasetAndUserWithCount();
+ break;
+ case "UserServiceDataset":
+ map = getAllServiceAndUserWithCount();
+ break;
+ case "DatasetServiceUser":
+ map = getAllServiceAndDatasetWithCount();
+ break;
+ default:
+ break;
+ }
+ return map;
+ }
+
+ public Result getRelationalKnowledgeGraph(String format) {
+ JsonNode json = request().body().asJson();
+
+ if (json == null) {
+ System.out.println("Cannot find relational knowledge graph, expecting Json data");
+ return badRequest("Cannot find relational knowledge graph, expecting Json data");
+ }
+ String param1 = json.findPath("param1").asText();
+ String param2 = json.findPath("param2").asText();
+ String param3 = json.findPath("param3").asText();
+
+ try {
+ Map<String, Object> map = generateRelationalMap(param1, param2, param3);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("Relationship not found");
+ }
+
+ }
+
+ public Map<String, Object> getAllServiceAndDatasetWithCount() {
+
+ Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+ .findAll();
+
+ if (datasetAndServices == null) {
+ System.out.println("Dataset and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndDataset(datasetAndServices);
+ return map;
+
+ }
+
+ public Map<String, Object> getAllDatasetAndUserWithCount() {
+
+ Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+ .findAll();
+
+ if (datasetAndUsers == null) {
+ System.out.println("User and Dataset: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatUserAndDataset(datasetAndUsers);
+ return map;
+ }
+
+ public Map<String, Object> getAllServiceAndUserWithCount() {
+
+ Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+ .findAll();
+
+ if (serviceAndUsers == null) {
+ System.out.println("User and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndUser(serviceAndUsers);
+ return map;
+ }
+
+ public Result getOneUserWithAllDatasetAndCount(long userId, String format) {
try {
- Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository.findAll();
+ User user = userRepository.findOne(userId);
+ Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+ .findByUser(user);
if (datasetAndUsers == null) {
System.out.println("User and Dataset: cannot be found!");
return notFound("User and Dataset: cannot be found!");
- }
+ }
- Map<String, Object> map = jsonFormat(datasetAndUsers);
+ Map<String, Object> map = jsonFormatUserAndDataset(datasetAndUsers);
String result = new String();
if (format.equals("json")) {
@@ -44,11 +318,140 @@
return ok(result);
} catch (Exception e) {
- return badRequest("DatasetLog not found");
+ return badRequest("User and Dataset not found");
}
}
- private Map<String, Object> jsonFormat(Iterable<DatasetAndUser> userDatasets) {
+ public Result getOneDatasetWithAllDatasetAndCount(long datasetId,
+ String format) {
+
+ try {
+ Dataset dataset = datasetRepository.findOne(datasetId);
+ Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+ .findByDataset(dataset);
+
+ if (datasetAndUsers == null) {
+ System.out.println("User and Dataset: cannot be found!");
+ return notFound("User and Dataset: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatUserAndDataset(datasetAndUsers);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("User and Dataset not found");
+ }
+ }
+
+ public Result getOneUserWithAllServiceAndCount(long userId, String format) {
+
+ try {
+ User user = userRepository.findOne(userId);
+ Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+ .findByUser(user);
+
+ if (serviceAndUsers == null) {
+ System.out.println("User and Service: cannot be found!");
+ return notFound("User and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndUser(serviceAndUsers);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("User and Service not found");
+ }
+ }
+
+ public Result getOneServiceWithAllUserAndCount(long serviceId, String format) {
+
+ try {
+ ClimateService service = serviceRepository.findOne(serviceId);
+ Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+ .findByClimateService(service);
+
+ if (serviceAndUsers == null) {
+ System.out.println("User and Service: cannot be found!");
+ return notFound("User and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndUser(serviceAndUsers);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("User and Service not found");
+ }
+ }
+
+ public Result getOneServiceWithAllDatasetAndCount(long serviceId,
+ String format) {
+
+ try {
+ ClimateService service = serviceRepository.findOne(serviceId);
+ Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+ .findByClimateService(service);
+
+ if (datasetAndServices == null) {
+ System.out.println("Dataset and Service: cannot be found!");
+ return notFound("Dataset and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndDataset(datasetAndServices);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("Dataset and Service not found");
+ }
+ }
+
+ public Result getOneDatasetWithAllServiceAndCount(long datasetId,
+ String format) {
+
+ try {
+ Dataset dataset = datasetRepository.findOne(datasetId);
+ Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+ .findByDataset(dataset);
+
+ if (datasetAndServices == null) {
+ System.out.println("Dataset and Service: cannot be found!");
+ return notFound("Dataset and Service: cannot be found!");
+ }
+
+ Map<String, Object> map = jsonFormatServiceAndDataset(datasetAndServices);
+
+ String result = new String();
+ if (format.equals("json")) {
+ result = new Gson().toJson(map);
+ }
+
+ return ok(result);
+ } catch (Exception e) {
+ return badRequest("Dataset and Service not found");
+ }
+ }
+
+ private Map<String, Object> jsonFormatUserAndDataset(
+ Iterable<DatasetAndUser> userDatasets) {
List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
@@ -59,31 +462,148 @@
int target = 0;
// Check whether the current user has already existed
for (int j = 0; j < nodes.size(); j++) {
- if (nodes.get(j).get("title")
- .equals(userDataset.getUser().getUserName())) {
+ if (nodes.get(j).get("group").equals("user")
+ && (long) nodes.get(j).get("userId") == userDataset
+ .getUser().getId()) {
source = (int) nodes.get(j).get("id");
break;
}
}
if (source == 0) {
- nodes.add(map6("id", i, "title", userDataset.getUser()
- .getUserName(), "label", "user", "cluster", "1",
- "value", 1, "group", "user"));
+ String realName = userDataset.getUser().getFirstName() + " "
+ + userDataset.getUser().getLastName();
+ nodes.add(map7("id", i, "title", realName, "label", userDataset
+ .getUser().getUserName(), "cluster", "1", "value", 1,
+ "group", "user", "userId", userDataset.getUser()
+ .getId()));
+
source = i;
i++;
}
// Check whether the current dataset has already existed
for (int j = 0; j < nodes.size(); j++) {
- if (nodes.get(j).get("title")
- .equals(userDataset.getDataset().getName())) {
+ if (nodes.get(j).get("group").equals("dataset")
+ && (long) nodes.get(j).get("datasetId") == userDataset
+ .getDataset().getId()) {
target = (int) nodes.get(j).get("id");
break;
}
}
if (target == 0) {
- nodes.add(map6("id", i, "title", userDataset.getDataset()
- .getName(), "label", "dataset", "cluster", "2",
- "value", 2, "group", "dataset"));
+ nodes.add(map7("id", i, "title", userDataset.getDataset()
+ .getName(), "label",
+ userDataset.getDataset().getName(), "cluster", "2",
+ "value", 2, "group", "dataset", "datasetId",
+ userDataset.getDataset().getId()));
+ target = i;
+ i++;
+ }
+ rels.add(map3("from", source, "to", target, "title", "USE"));
+
+ }
+
+ return map("nodes", nodes, "edges", rels);
+ }
+
+ private Map<String, Object> jsonFormatServiceAndDataset(
+ Iterable<ServiceAndDataset> serviceDatasets) {
+
+ List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+ List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+
+ int i = 1;
+ for (ServiceAndDataset serviceDataset : serviceDatasets) {
+ int source = 0;
+ int target = 0;
+ // Check whether the current service has already existed
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals("service")
+ && (long) nodes.get(j).get("serviceId") == serviceDataset
+ .getClimateService().getId()) {
+ source = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (source == 0) {
+ nodes.add(map7("id", i, "title", serviceDataset
+ .getClimateService().getName(), "label", serviceDataset
+ .getClimateService().getName(), "cluster", "3",
+ "value", 1, "group", "service", "serviceId",
+ serviceDataset.getClimateService().getId()));
+ source = i;
+ i++;
+ }
+ // Check whether the current dataset has already existed
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals("dataset")
+ && (long) nodes.get(j).get("datasetId") == serviceDataset
+ .getDataset().getId()) {
+ target = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (target == 0) {
+ nodes.add(map7("id", i, "title", serviceDataset.getDataset()
+ .getName(), "label", serviceDataset.getDataset()
+ .getName(), "cluster", "2", "value", 2, "group",
+ "dataset", "datasetId", serviceDataset.getDataset()
+ .getId()));
+ target = i;
+ i++;
+ }
+
+ rels.add(map3("from", source, "to", target, "title", "Utilize"));
+
+ }
+
+ return map("nodes", nodes, "edges", rels);
+ }
+
+ private Map<String, Object> jsonFormatServiceAndUser(
+ Iterable<ServiceAndUser> userServices) {
+
+ List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+ List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+
+ int i = 1;
+ for (ServiceAndUser userService : userServices) {
+ int source = 0;
+ int target = 0;
+ // Check whether the current user has already existed
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals("user")
+ && (long) nodes.get(j).get("userId") == userService
+ .getUser().getId()) {
+ source = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (source == 0) {
+ String realName = userService.getUser().getFirstName() + " "
+ + userService.getUser().getMiddleInitial() + " "
+ + userService.getUser().getLastName();
+ nodes.add(map7("id", i, "title", realName, "label", userService
+ .getUser().getUserName(), "cluster", "1", "value", 1,
+ "group", "user", "userId", userService.getUser()
+ .getId()));
+ source = i;
+ i++;
+ }
+ // Check whether the current service has already existed
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals("service")
+ && (long) nodes.get(j).get("serviceId") == userService
+ .getClimateService().getId()) {
+ target = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (target == 0) {
+ nodes.add(map7("id", i, "title", userService
+ .getClimateService().getName(), "label", userService
+ .getClimateService().getName(), "cluster", "3",
+ "value", 2, "group", "service", "serviceId",
+ userService.getClimateService().getId()));
target = i;
i++;
}
@@ -94,6 +614,74 @@
return map("nodes", nodes, "edges", rels);
}
+
+ public String findTitleName(String param, long id) {
+ String title = "";
+ switch (param) {
+ case "user":
+ title = userRepository.findOne(id).getUserName();
+ break;
+ case "dataset":
+ title = datasetRepository.findOne(id).getName();
+ break;
+ case "service":
+ title = serviceRepository.findOne(id).getName();
+ break;
+ default:
+ break;
+ }
+ return title;
+ }
+
+ private Map<String, Object> jsonFormatForMatrix(int[][] matrix, String param) {
+
+ List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+ List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+
+ int i = 1;
+ for (int m = 0; m < matrix.length; m++) {
+ for (int n = m + 1; n < matrix[0].length; n++) {
+ if (matrix[m][n] > 0) {
+ int source = 0;
+ int target = 0;
+ // Check whether the current user has already existed
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals(param)
+ && (long) nodes.get(j).get(param + "Id") == (long)m + 1) {
+ source = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (source == 0) {
+ String name = findTitleName(param, (long)m+1);
+ nodes.add(map7("id", i, "title", name, "label",
+ name, "cluster", "1", "value", 1, "group",
+ param, param + "Id", (long)m + 1));
+ source = i;
+ i++;
+ }
+ for (int j = 0; j < nodes.size(); j++) {
+ if (nodes.get(j).get("group").equals(param)
+ && (long) nodes.get(j).get(param + "Id") == (long)n + 1) {
+ target = (int) nodes.get(j).get("id");
+ break;
+ }
+ }
+ if (target == 0) {
+ String name = findTitleName(param, (long)n+1);
+ nodes.add(map7("id", i, "title", name, "label",
+ name, "cluster", "1", "value", 1, "group",
+ param, param + "Id", (long)n + 1));
+ target = i;
+ i++;
+ }
+ rels.add(map3("from", source, "to", target, "title", "RELATE"));
+ }
+ }
+ }
+
+ return map("nodes", nodes, "edges", rels);
+ }
private Map<String, Object> map(String key1, Object value1, String key2,
Object value2) {
@@ -112,10 +700,10 @@
return result;
}
- private Map<String, Object> map6(String key1, Object value1, String key2,
+ private Map<String, Object> map7(String key1, Object value1, String key2,
Object value2, String key3, Object value3, String key4,
Object value4, String key5, Object value5, String key6,
- Object value6) {
+ Object value6, String key7, Object value7) {
Map<String, Object> result = new HashMap<String, Object>(6);
result.put(key1, value1);
result.put(key2, value2);
@@ -123,6 +711,7 @@
result.put(key4, value4);
result.put(key5, value5);
result.put(key6, value6);
+ result.put(key7, value7);
return result;
}
}
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/ClimateServiceController.java b/ApacheCMDA_Backend_1.0/app/controllers/ClimateServiceController.java
index 700ad68..e42f8b6 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/ClimateServiceController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/ClimateServiceController.java
@@ -32,6 +32,7 @@
@Named
@Singleton
public class ClimateServiceController extends Controller {
+ public static final String WILDCARD = "%";
private final int initialcount = 0;
// static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ssz";
@@ -490,4 +491,60 @@
}
return ok(result);
}
+
+ public Result queryClimateServices() {
+ JsonNode json = request().body().asJson();
+ if (json == null) {
+ System.out.println("ClimateService cannot be queried, expecting Json data");
+ return badRequest("ClimateService cannot be queried, expecting Json data");
+ }
+ String result = new String();
+ try {
+ //Parse JSON file
+ String name = json.path("name").asText();
+ if (name.isEmpty()) {
+ name = WILDCARD;
+ }
+ else {
+ name = WILDCARD+name+WILDCARD;
+ }
+ String purpose = json.path("purpose").asText();
+ if (purpose.isEmpty()) {
+ purpose = WILDCARD;
+ }
+ else {
+ purpose = WILDCARD+purpose+WILDCARD;
+ }
+ String url = json.path("url").asText();
+ if (url.isEmpty()) {
+ url = WILDCARD;
+ }
+ else {
+ url = WILDCARD+url+WILDCARD;
+ }
+ String scenario = json.path("scenario").asText();
+ if (scenario.isEmpty()) {
+ scenario = WILDCARD;
+ }
+ else {
+ scenario = WILDCARD+scenario+WILDCARD;
+ }
+ String versionNo = json.path("versionNo").asText();
+ if (versionNo.isEmpty()) {
+ versionNo = WILDCARD;
+ }
+ else {
+ versionNo = WILDCARD+versionNo+WILDCARD;
+ }
+
+ List<ClimateService> climateServices = climateServiceRepository.findClimateService(name, purpose, url, scenario, versionNo);
+ result = new Gson().toJson(climateServices);
+ } catch (Exception e) {
+ System.out.println("ServiceExecutionLog cannot be queried, query is corrupt");
+ return badRequest("ServiceExecutionLog cannot be queried, query is corrupt");
+ }
+
+ System.out.println("*******************************\n&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n" + result);
+ return ok(result);
+ }
}
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java b/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
index e4594a8..9d5dad2 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
@@ -12,6 +12,8 @@
import models.ClimateService;
import models.ClimateServiceRepository;
import models.Dataset;
+import models.DatasetAndUser;
+import models.DatasetAndUserRepository;
import models.DatasetEntry;
import models.DatasetEntryRepository;
import models.DatasetLog;
@@ -54,6 +56,7 @@
private final ServiceConfigurationItemRepository serviceConfigurationItemRepository;
private final DatasetLogRepository datasetLogRepository;
private final ServiceConfigurationRepository serviceConfigurationRepository;
+ private final DatasetAndUserRepository datasetAndUserRepository;
// We are using constructor injection to receive a repository to support our
// desire for immutability.
@@ -68,7 +71,8 @@
ServiceConfigurationRepository serviceConfigurationRepository,
ServiceEntryRepository serviceEntryRepository,
DatasetEntryRepository datasetEntryRepository,
- DatasetRepository datasetRepository) {
+ DatasetRepository datasetRepository,
+ DatasetAndUserRepository datasetAndUserRepository) {
this.parameterRepository = parameterRepository;
this.serviceExecutionLogRepository = serviceExecutionLogRepository;
this.userRepository = userRepository;
@@ -79,6 +83,7 @@
this.serviceEntryRepository = serviceEntryRepository;
this.datasetEntryRepository = datasetEntryRepository;
this.datasetRepository = datasetRepository;
+ this.datasetAndUserRepository = datasetAndUserRepository;
}
public Result queryServiceExecutionLogs() {
@@ -477,8 +482,18 @@
dataset, user, plotUrl, dataUrl, dataset,
dataset, datasetStudyStartTime, datasetStudyEndTime);
DatasetLog savedDatasetLog = datasetLogRepository.save(datasetLog);
- System.out.println(dataset.toString());
System.out.print("DatasetLog saved:" + savedDatasetLog.getId());
+
+ List<DatasetAndUser> datasetAndUsers = datasetAndUserRepository.findByUserAndDataset(user, dataset);
+ if(datasetAndUsers.size() == 0) {
+ DatasetAndUser datasetAndUser = new DatasetAndUser(user, dataset, 0);
+ datasetAndUserRepository.save(datasetAndUser);
+ }
+ else {
+ DatasetAndUser datasetAndUser = datasetAndUsers.get(0);
+ datasetAndUser.setCount(datasetAndUser.getCount() + 1);
+ datasetAndUserRepository.save(datasetAndUser);
+ }
}
}
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/WorkflowController.java b/ApacheCMDA_Backend_1.0/app/controllers/WorkflowController.java
index e01909a..41c9e99 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/WorkflowController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/WorkflowController.java
@@ -24,6 +24,7 @@
import models.ClimateService;
import models.ClimateServiceRepository;
+import models.DatasetAndUserRepository;
import models.DatasetEntryRepository;
import models.DatasetLogRepository;
import models.DatasetRepository;
@@ -59,6 +60,7 @@
private final ServiceEntryRepository serviceEntryRepository;
private final DatasetEntryRepository datasetEntryRepository;
private final DatasetRepository datasetRepository;
+ private final DatasetAndUserRepository datasetAndUserRepository;
@Inject
public WorkflowController(
@@ -72,7 +74,8 @@
ServiceConfigurationRepository serviceConfigurationRepository,
ServiceEntryRepository serviceEntryRepository,
DatasetEntryRepository datasetEntryRepository,
- DatasetRepository datasetRepository) {
+ DatasetRepository datasetRepository,
+ DatasetAndUserRepository datasetAndUserRepository) {
this.climateServiceRepository = climateServiceRepository;
this.userRepository = userRepository;
this.workflowRepository = workflowRepository;
@@ -84,6 +87,7 @@
this.serviceEntryRepository = serviceEntryRepository;
this.datasetEntryRepository = datasetEntryRepository;
this.datasetRepository = datasetRepository;
+ this.datasetAndUserRepository = datasetAndUserRepository;
}
public Result addWorkflow() {
@@ -227,7 +231,7 @@
serviceConfigurationItemRepository, userRepository,
climateServiceRepository, datasetLogRepository,
serviceConfigurationRepository, serviceEntryRepository,
- datasetEntryRepository, datasetRepository);
+ datasetEntryRepository, datasetRepository, datasetAndUserRepository);
List<ServiceExecutionLog> list = serviceExecutionLogController
.queryServiceExecutionLogsAsList();
String result = VisTrailJson.getVisTrailJson(list);
diff --git a/ApacheCMDA_Backend_1.0/app/models/ClimateServiceRepository.java b/ApacheCMDA_Backend_1.0/app/models/ClimateServiceRepository.java
index 2f70c53..5a8090b 100644
--- a/ApacheCMDA_Backend_1.0/app/models/ClimateServiceRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/ClimateServiceRepository.java
@@ -24,4 +24,8 @@
@Query(value = "select * from ClimateService where id in (select serviceId from ServiceEntry s where serviceId in (select climateServiceId from DatasetAndService where datasetId=?2) group by s.serviceId order by s.latestAccessTimeStamp desc) limit ?1", nativeQuery = true)
List<ClimateService> getClimateServiceByDatasetId(int k, long id);
+
+ @Query(value = "select * from ClimateService where ((name like ?1) and (purpose like ?2) and (url like ?3) and (scenario like ?4) and (versionNo like ?5))", nativeQuery = true)
+ List<ClimateService> findClimateService(String name, String purpose, String url, String scenario, String versionNo);
+
}
diff --git a/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java b/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
index ce6b046..f6d8e27 100644
--- a/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
@@ -1,5 +1,7 @@
package models;
+import java.util.List;
+
import org.springframework.data.repository.CrudRepository;
import javax.inject.Named;
@@ -8,5 +10,8 @@
@Named
@Singleton
public interface DatasetAndUserRepository extends CrudRepository<DatasetAndUser, Long> {
-
+
+ List<DatasetAndUser> findByUserAndDataset(User user, Dataset dataset);
+ List<DatasetAndUser> findByUser(User user);
+ List<DatasetAndUser> findByDataset(Dataset dataset);
}
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndDataset.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDataset.java
new file mode 100644
index 0000000..8ae0392
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDataset.java
@@ -0,0 +1,68 @@
+package models;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class ServiceAndDataset {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+ @ManyToOne(optional = false)
+ @JoinColumn(name = "serviceId", referencedColumnName = "id")
+ private ClimateService climateService;
+ @ManyToOne(optional = false)
+ @JoinColumn(name = "datasetId", referencedColumnName = "id")
+ private Dataset dataset;
+ private long count;
+
+ public ServiceAndDataset() {
+ }
+
+ public ServiceAndDataset(ClimateService climateService, Dataset dataset, long count) {
+ this.climateService = climateService;
+ this.dataset = dataset;
+ this.count = count;
+ }
+
+ public ClimateService getClimateService() {
+ return climateService;
+ }
+
+ public void setClimateService(ClimateService climateService) {
+ this.climateService = climateService;
+ }
+
+ public Dataset getDataset() {
+ return dataset;
+ }
+
+ public void setDataset(Dataset dataset) {
+ this.dataset = dataset;
+ }
+
+ public long getCount() {
+ return count;
+ }
+
+ public void setCount(long count) {
+ this.count = count;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "ServiceAndDataset [id=" + id + ", climateService="
+ + climateService + ", dataset=" + dataset + ", count=" + count
+ + "]";
+ }
+
+}
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java
new file mode 100644
index 0000000..14258b3
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java
@@ -0,0 +1,18 @@
+package models;
+
+import java.util.List;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface ServiceAndDatasetRepository extends CrudRepository<ServiceAndDataset, Long> {
+
+ List<ServiceAndDataset> findByClimateService(ClimateService service);
+ List<ServiceAndDataset> findByDataset(Dataset dataset);
+
+}
+
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndUser.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUser.java
new file mode 100644
index 0000000..42806f0
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUser.java
@@ -0,0 +1,69 @@
+package models;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class ServiceAndUser {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+ @ManyToOne(optional = false)
+ @JoinColumn(name = "userId", referencedColumnName = "id")
+ private User user;
+ @ManyToOne(optional = false)
+ @JoinColumn(name = "serviceId", referencedColumnName = "id")
+ private ClimateService climateService;
+ private long count;
+
+ public ServiceAndUser() {
+ }
+
+ public ServiceAndUser(User user, ClimateService climateService, long count) {
+ this.user = user;
+ this.climateService = climateService;
+ this.count = count;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public long getCount() {
+ return count;
+ }
+
+ public void setCount(long count) {
+ this.count = count;
+ }
+
+ public ClimateService getClimateService() {
+ return climateService;
+ }
+
+ @Override
+ public String toString() {
+ return "ServiceAndUser [id=" + id + ", user=" + user
+ + ", climateService=" + climateService + ", count=" + count
+ + "]";
+ }
+
+}
+
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java
new file mode 100644
index 0000000..4f1c960
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java
@@ -0,0 +1,18 @@
+package models;
+
+import java.util.List;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface ServiceAndUserRepository extends CrudRepository<ServiceAndUser, Long> {
+
+ List<ServiceAndUser> findByUser(User user);
+ List<ServiceAndUser> findByClimateService(ClimateService service);
+
+}
+
diff --git a/ApacheCMDA_Backend_1.0/app/util/Matrix.java b/ApacheCMDA_Backend_1.0/app/util/Matrix.java
new file mode 100644
index 0000000..407ef04
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/util/Matrix.java
@@ -0,0 +1,234 @@
+package util;
+
+public class Matrix {
+ private final int M; // number of rows
+ private final int N; // number of columns
+ private final int[][] data; // M-by-N array
+
+ // create M-by-N matrix of 0's
+ public Matrix(int M, int N) {
+ this.M = M;
+ this.N = N;
+ data = new int[M][N];
+ }
+
+ // create matrix based on 2d array
+ public Matrix(int[][] data) {
+ M = data.length;
+ N = data[0].length;
+ this.data = new int[M][N];
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ this.data[i][j] = data[i][j];
+ }
+
+ // copy constructor
+ private Matrix(Matrix A) {
+ this(A.data);
+ }
+
+ // create and return a random M-by-N matrix with values between 0 and 1
+ // Change: A.data[i][j] = Math.random();
+ public static Matrix random(int M, int N) {
+ Matrix A = new Matrix(M, N);
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ A.data[i][j] = (int) Math.random();
+ return A;
+ }
+
+ // create and return the N-by-N identity matrix
+ public static Matrix identity(int N) {
+ Matrix I = new Matrix(N, N);
+ for (int i = 0; i < N; i++)
+ I.data[i][i] = 1;
+ return I;
+ }
+
+ // swap rows i and j
+ private void swap(int i, int j) {
+ int[] temp = data[i];
+ data[i] = data[j];
+ data[j] = temp;
+ }
+
+ // create and return the transpose of the invoking matrix
+ public Matrix transpose() {
+ Matrix A = new Matrix(N, M);
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ A.data[j][i] = this.data[i][j];
+ return A;
+ }
+
+ // return C = A + B
+ public Matrix plus(Matrix B) {
+ Matrix A = this;
+ if (B.M != A.M || B.N != A.N)
+ throw new RuntimeException("Illegal matrix dimensions.");
+ Matrix C = new Matrix(M, N);
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ C.data[i][j] = A.data[i][j] + B.data[i][j];
+ return C;
+ }
+
+ // return C = A - B
+ public Matrix minus(Matrix B) {
+ Matrix A = this;
+ if (B.M != A.M || B.N != A.N)
+ throw new RuntimeException("Illegal matrix dimensions.");
+ Matrix C = new Matrix(M, N);
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ C.data[i][j] = A.data[i][j] - B.data[i][j];
+ return C;
+ }
+
+ // does A = B exactly?
+ public boolean eq(Matrix B) {
+ Matrix A = this;
+ if (B.M != A.M || B.N != A.N)
+ throw new RuntimeException("Illegal matrix dimensions.");
+ for (int i = 0; i < M; i++)
+ for (int j = 0; j < N; j++)
+ if (A.data[i][j] != B.data[i][j])
+ return false;
+ return true;
+ }
+
+ // return C = A * B
+ public Matrix times(Matrix B) {
+ Matrix A = this;
+ if (A.N != B.M)
+ throw new RuntimeException("Illegal matrix dimensions.");
+ Matrix C = new Matrix(A.M, B.N);
+ for (int i = 0; i < C.M; i++)
+ for (int j = 0; j < C.N; j++)
+ for (int k = 0; k < A.N; k++)
+ C.data[i][j] += (A.data[i][k] * B.data[k][j]);
+ return C;
+ }
+
+ // return x = A^-1 b, assuming A is square and has full rank
+ // Cast (int)
+ public Matrix solve(Matrix rhs) {
+ if (M != N || rhs.M != N || rhs.N != 1)
+ throw new RuntimeException("Illegal matrix dimensions.");
+
+ // create copies of the data
+ Matrix A = new Matrix(this);
+ Matrix b = new Matrix(rhs);
+
+ // Gaussian elimination with partial pivoting
+ for (int i = 0; i < N; i++) {
+
+ // find pivot row and swap
+ int max = i;
+ for (int j = i + 1; j < N; j++)
+ if (Math.abs(A.data[j][i]) > Math.abs(A.data[max][i]))
+ max = j;
+ A.swap(i, max);
+ b.swap(i, max);
+
+ // singular
+ if (A.data[i][i] == 0)
+ throw new RuntimeException("Matrix is singular.");
+
+ // pivot within b
+ for (int j = i + 1; j < N; j++)
+ b.data[j][0] -= b.data[i][0] * A.data[j][i] / A.data[i][i];
+
+ // pivot within A
+ for (int j = i + 1; j < N; j++) {
+ double m = A.data[j][i] / A.data[i][i];
+ for (int k = i + 1; k < N; k++) {
+ A.data[j][k] -= A.data[i][k] * m;
+ }
+ A.data[j][i] = 0;
+ }
+ }
+
+ // back substitution
+ Matrix x = new Matrix(N, 1);
+ for (int j = N - 1; j >= 0; j--) {
+ double t = 0.0;
+ for (int k = j + 1; k < N; k++)
+ t += A.data[j][k] * x.data[k][0];
+ x.data[j][0] = (int) ((b.data[j][0] - t) / A.data[j][j]);
+ }
+ return x;
+
+ }
+
+ // print matrix to standard output
+ public void show() {
+ for (int i = 0; i < M; i++) {
+ for (int j = 0; j < N; j++)
+ System.out.printf("%d ", data[i][j]);
+ System.out.println();
+ }
+ }
+
+ // print matrix to standard output
+ public int[][] getArray() {
+ return data;
+ }
+
+ // test client
+ public static void main(String[] args) {
+ int[][] d = { { 1, 2, 3 }, { 4, 5, 6 }, { 9, 1, 3 } };
+ Matrix D = new Matrix(d);
+ D.show();
+ System.out.println();
+
+ int[][] a = D.getArray();
+ for(int[] i : a) {
+ for(int j : i) {
+ System.out.printf("%d ", j);
+ }
+ System.out.println();
+ }
+ System.out.println();
+
+
+ Matrix A = D;
+ A.show();
+ System.out.println();
+
+ A.swap(1, 2);
+ A.show();
+ System.out.println();
+
+ Matrix B = A.transpose();
+ B.show();
+ System.out.println();
+
+ Matrix C = Matrix.identity(5);
+ C.show();
+ System.out.println();
+
+ A.plus(B).show();
+ System.out.println();
+
+ B.times(A).show();
+ System.out.println();
+
+ // shouldn't be equal since AB != BA in general
+ System.out.println(A.times(B).eq(B.times(A)));
+ System.out.println();
+
+ Matrix b = Matrix.random(5, 1);
+ b.show();
+ System.out.println();
+
+ Matrix x = A.solve(b);
+ x.show();
+ System.out.println();
+
+ A.times(x).show();
+
+
+
+ }
+}
diff --git a/ApacheCMDA_Backend_1.0/conf/.DS_Store b/ApacheCMDA_Backend_1.0/conf/.DS_Store
new file mode 100644
index 0000000..c7bbec7
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/conf/.DS_Store
Binary files differ
diff --git a/ApacheCMDA_Backend_1.0/conf/routes b/ApacheCMDA_Backend_1.0/conf/routes
index b59bff7..3846661 100644
--- a/ApacheCMDA_Backend_1.0/conf/routes
+++ b/ApacheCMDA_Backend_1.0/conf/routes
@@ -15,6 +15,7 @@
GET /climateService/getAllMostUsedClimateServices/json @controllers.ClimateServiceController.getAllClimateServicesOrderByCount(format: String="json")
GET /climateService/getTopKUsedClimateServicesByDatasetId/:id @controllers.ClimateServiceController.getTopKUsedClimateServicesByDatasetId(id: Long, format: String="json")
POST /climateService/addClimateService @controllers.ClimateServiceController.addClimateService
+POST /climateService/queryClimateService @controllers.ClimateServiceController.queryClimateServices
GET /climateService/getAllServiceEntries/json @controllers.ClimateServiceController.getAllServiceEntries(format: String="json")
POST /climateService/addServiceEntry @controllers.ClimateServiceController.addServiceEntry
PUT /climateService/updateClimateService/id/:id @controllers.ClimateServiceController.updateClimateServiceById(id: Long)
@@ -138,7 +139,16 @@
DELETE /users/delete/userName/:userName/password/:password @controllers.UserController.deleteUserByUserNameandPassword(userName: String, password: String)
# Analytics
-GET /analytics/getAllDatasetAndUserWithCount/json @controllers.AnalyticsController.getAllDatasetAndUserWithCount(format: String="json")
+#GET /analytics/getAllDatasetAndUserWithCount/json @controllers.AnalyticsController.getAllDatasetAndUserWithCount(format: String="json")
+#GET /analytics/getAllServiceAndUserWithCount/json @controllers.AnalyticsController.getAllServiceAndUserWithCount(format: String="json")
+#GET /analytics/getAllServiceAndDatasetWithCount/json @controllers.AnalyticsController.getAllServiceAndDatasetWithCount(format: String="json")
+GET /analytics/getOneUserWithAllDatasetAndCountByUserId/:id/json @controllers.AnalyticsController.getOneUserWithAllDatasetAndCount(id: Long, format: String="json")
+GET /analytics/getOneDatasetWithAllDatasetAndCountByDatasetId/:id/json @controllers.AnalyticsController.getOneDatasetWithAllDatasetAndCount(id: Long, format: String="json")
+GET /analytics/getOneUserWithAllServiceAndCountByUserId/:id/json @controllers.AnalyticsController.getOneUserWithAllServiceAndCount(id: Long, format: String="json")
+GET /analytics/getOneServiceWithAllUserAndCountByServiceId/:id/json @controllers.AnalyticsController.getOneServiceWithAllUserAndCount(id: Long, format: String="json")
+GET /analytics/getOneServiceWithAllDatasetAndCountByServiceId/:id/json @controllers.AnalyticsController.getOneServiceWithAllDatasetAndCount(id: Long, format: String="json")
+GET /analytics/getOneDatasetWithAllServiceAndCountByDatasetId/:id/json @controllers.AnalyticsController.getOneDatasetWithAllServiceAndCount(id: Long, format: String="json")
+POST /analytics/getRelationalKnowledgeGraph/json @controllers.AnalyticsController.getRelationalKnowledgeGraph(format: String="json")
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)