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)