Update Backend: Add APIs in knowlege graph to support shortest path; Add length feature to edges; Add search query for datasetLog based on knowledge graph
diff --git a/ApacheCMDA_Backend_1.0/app/.DS_Store b/ApacheCMDA_Backend_1.0/app/.DS_Store
index 01d5243..e8a7ea5 100644
--- a/ApacheCMDA_Backend_1.0/app/.DS_Store
+++ b/ApacheCMDA_Backend_1.0/app/.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 f5f44d4..713aacc 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/AnalyticsController.java
@@ -9,6 +9,8 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import org.springframework.data.domain.Sort;
+
 import models.ClimateService;
 import models.ClimateServiceRepository;
 import models.Dataset;
@@ -23,6 +25,7 @@
 import models.UserRepository;
 import play.mvc.Controller;
 import play.mvc.Result;
+import util.HashMapUtil;
 import util.Matrix;
 
 import com.fasterxml.jackson.databind.JsonNode;
@@ -82,7 +85,7 @@
 		case "UserUserDataset": {
 			relations = new int[count1][count3];
 			Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (datasetAndUsers == null) {
 				System.out.println("User and Dataset: cannot be found!");
@@ -105,7 +108,7 @@
 		case "UserUserService": {
 			relations = new int[count1][count3];
 			Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (serviceAndUsers == null) {
 				System.out.println("User and Service: cannot be found!");
@@ -128,7 +131,7 @@
 		case "DatasetDatasetUser": {
 			relations = new int[count1][count3];
 			Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (datasetAndUsers == null) {
 				System.out.println("User and Dataset: cannot be found!");
@@ -151,7 +154,7 @@
 		case "DatasetDatasetService": {
 			relations = new int[count1][count3];
 			Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (datasetAndServices == null) {
 				System.out.println("Dataset and Service: cannot be found!");
@@ -174,7 +177,7 @@
 		case "ServiceServiceUser": {
 			relations = new int[count1][count3];
 			Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (serviceAndUsers == null) {
 				System.out.println("User and Service: cannot be found!");
@@ -197,7 +200,7 @@
 		case "ServiceServiceDataset": {
 			relations = new int[count1][count3];
 			Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
-					.findAll();
+					.findAll(sortByCountDesc());
 
 			if (datasetAndServices == null) {
 				System.out.println("Dataset and Service: cannot be found!");
@@ -259,13 +262,13 @@
 
 	public Map<String, Object> getAllServiceAndDatasetWithCount() {
 
-		Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
-				.findAll();
+		List<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+				.findAll(sortByCountDesc());
 
 		if (datasetAndServices == null) {
 			System.out.println("Dataset and Service: cannot be found!");
 		}
-
+		
 		Map<String, Object> map = jsonFormatServiceAndDataset(datasetAndServices);
 		return map;
 
@@ -273,8 +276,8 @@
 
 	public Map<String, Object> getAllDatasetAndUserWithCount() {
 
-		Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
-				.findAll();
+		List<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+				.findAll(sortByCountDesc());
 
 		if (datasetAndUsers == null) {
 			System.out.println("User and Dataset: cannot be found!");
@@ -286,8 +289,8 @@
 
 	public Map<String, Object> getAllServiceAndUserWithCount() {
 
-		Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
-				.findAll();
+		List<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+				.findAll(sortByCountDesc());
 
 		if (serviceAndUsers == null) {
 			System.out.println("User and Service: cannot be found!");
@@ -301,7 +304,7 @@
 
 		try {
 			User user = userRepository.findOne(userId);
-			Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+			List<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
 					.findByUser(user);
 
 			if (datasetAndUsers == null) {
@@ -322,12 +325,12 @@
 		}
 	}
 
-	public Result getOneDatasetWithAllDatasetAndCount(long datasetId,
+	public Result getOneDatasetWithAllUserAndCount(long datasetId,
 			String format) {
 
 		try {
 			Dataset dataset = datasetRepository.findOne(datasetId);
-			Iterable<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
+			List<DatasetAndUser> datasetAndUsers = datasetAndUserRepository
 					.findByDataset(dataset);
 
 			if (datasetAndUsers == null) {
@@ -352,7 +355,7 @@
 
 		try {
 			User user = userRepository.findOne(userId);
-			Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+			List<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
 					.findByUser(user);
 
 			if (serviceAndUsers == null) {
@@ -377,7 +380,7 @@
 
 		try {
 			ClimateService service = serviceRepository.findOne(serviceId);
-			Iterable<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
+			List<ServiceAndUser> serviceAndUsers = serviceAndUserRepository
 					.findByClimateService(service);
 
 			if (serviceAndUsers == null) {
@@ -403,7 +406,7 @@
 
 		try {
 			ClimateService service = serviceRepository.findOne(serviceId);
-			Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+			List<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
 					.findByClimateService(service);
 
 			if (datasetAndServices == null) {
@@ -429,7 +432,7 @@
 
 		try {
 			Dataset dataset = datasetRepository.findOne(datasetId);
-			Iterable<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
+			List<ServiceAndDataset> datasetAndServices = serviceAndDatasetRepository
 					.findByDataset(dataset);
 
 			if (datasetAndServices == null) {
@@ -451,12 +454,14 @@
 	}
 
 	private Map<String, Object> jsonFormatUserAndDataset(
-			Iterable<DatasetAndUser> userDatasets) {
-
+			List<DatasetAndUser> userDatasets) {
+		long min = userDatasets.get(userDatasets.size()-1).getCount();
+		long max = userDatasets.get(0).getCount();
 		List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
 		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
 
 		int i = 1;
+		int edgeId = 1;
 		for (DatasetAndUser userDataset : userDatasets) {
 			int source = 0;
 			int target = 0;
@@ -472,7 +477,7 @@
 			if (source == 0) {
 				String realName = userDataset.getUser().getFirstName() + " "
 						+ userDataset.getUser().getLastName();
-				nodes.add(map7("id", i, "title", realName, "label", userDataset
+				nodes.add(HashMapUtil.map7("id", i, "title", realName, "label", userDataset
 						.getUser().getUserName(), "cluster", "1", "value", 1,
 						"group", "user", "userId", userDataset.getUser()
 								.getId()));
@@ -490,7 +495,7 @@
 				}
 			}
 			if (target == 0) {
-				nodes.add(map7("id", i, "title", userDataset.getDataset()
+				nodes.add(HashMapUtil.map7("id", i, "title", userDataset.getDataset()
 						.getName(), "label",
 						userDataset.getDataset().getName(), "cluster", "2",
 						"value", 2, "group", "dataset", "datasetId",
@@ -498,20 +503,24 @@
 				target = i;
 				i++;
 			}
-			rels.add(map3("from", source, "to", target, "title", "USE"));
-
+			rels.add(HashMapUtil.map6("from", source, "to", target, "title", "USE",
+					"id", edgeId, "weight", userDataset.getCount(), "length", (max-min)*3/userDataset.getCount()));
+			edgeId++;
 		}
 
-		return map("nodes", nodes, "edges", rels);
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
 	}
 
 	private Map<String, Object> jsonFormatServiceAndDataset(
-			Iterable<ServiceAndDataset> serviceDatasets) {
-
+			List<ServiceAndDataset> serviceDatasets) {
+		
+		long min = serviceDatasets.get(serviceDatasets.size()-1).getCount();
+		long max = serviceDatasets.get(0).getCount();
 		List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
 		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
 
 		int i = 1;
+		int edgeId = 1;
 		for (ServiceAndDataset serviceDataset : serviceDatasets) {
 			int source = 0;
 			int target = 0;
@@ -525,7 +534,7 @@
 				}
 			}
 			if (source == 0) {
-				nodes.add(map7("id", i, "title", serviceDataset
+				nodes.add(HashMapUtil.map7("id", i, "title", serviceDataset
 						.getClimateService().getName(), "label", serviceDataset
 						.getClimateService().getName(), "cluster", "3",
 						"value", 1, "group", "service", "serviceId",
@@ -543,7 +552,7 @@
 				}
 			}
 			if (target == 0) {
-				nodes.add(map7("id", i, "title", serviceDataset.getDataset()
+				nodes.add(HashMapUtil.map7("id", i, "title", serviceDataset.getDataset()
 						.getName(), "label", serviceDataset.getDataset()
 						.getName(), "cluster", "2", "value", 2, "group",
 						"dataset", "datasetId", serviceDataset.getDataset()
@@ -552,20 +561,24 @@
 				i++;
 			}
 
-			rels.add(map3("from", source, "to", target, "title", "Utilize"));
-
+			rels.add(HashMapUtil.map6("from", source, "to", target, "title", "Utilize",
+					"id", edgeId, "weight", serviceDataset.getCount(), "length", (max-min)*3/serviceDataset.getCount()));
+			edgeId++;
 		}
 
-		return map("nodes", nodes, "edges", rels);
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
 	}
 
 	private Map<String, Object> jsonFormatServiceAndUser(
-			Iterable<ServiceAndUser> userServices) {
-
+			List<ServiceAndUser> userServices) {
+		
+		long min = userServices.get(userServices.size()-1).getCount();
+		long max = userServices.get(0).getCount();
 		List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
 		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
 
 		int i = 1;
+		int edgeId = 1;
 		for (ServiceAndUser userService : userServices) {
 			int source = 0;
 			int target = 0;
@@ -580,9 +593,8 @@
 			}
 			if (source == 0) {
 				String realName = userService.getUser().getFirstName() + " "
-						+ userService.getUser().getMiddleInitial() + " "
 						+ userService.getUser().getLastName();
-				nodes.add(map7("id", i, "title", realName, "label", userService
+				nodes.add(HashMapUtil.map7("id", i, "title", realName, "label", userService
 						.getUser().getUserName(), "cluster", "1", "value", 1,
 						"group", "user", "userId", userService.getUser()
 								.getId()));
@@ -599,7 +611,7 @@
 				}
 			}
 			if (target == 0) {
-				nodes.add(map7("id", i, "title", userService
+				nodes.add(HashMapUtil.map7("id", i, "title", userService
 						.getClimateService().getName(), "label", userService
 						.getClimateService().getName(), "cluster", "3",
 						"value", 2, "group", "service", "serviceId",
@@ -608,11 +620,12 @@
 				i++;
 			}
 
-			rels.add(map3("from", source, "to", target, "title", "USE"));
-
+			rels.add(HashMapUtil.map6("from", source, "to", target, "title", "USE",
+					"id", edgeId, "weight", userService.getCount(), "length", (max-min)*4/userService.getCount()));
+			edgeId ++;
 		}
 
-		return map("nodes", nodes, "edges", rels);
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
 	}
 	
 	public String findTitleName(String param, long id) {
@@ -639,6 +652,7 @@
 		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
 
 		int i = 1;
+		int edgeId = 1;
 		for (int m = 0; m < matrix.length; m++) {
 			for (int n = m + 1; n < matrix[0].length; n++) {
 				if (matrix[m][n] > 0) {
@@ -654,7 +668,7 @@
 					}
 					if (source == 0) {
 						String name = findTitleName(param, (long)m+1);
-						nodes.add(map7("id", i, "title", name, "label",
+						nodes.add(HashMapUtil.map7("id", i, "title", name, "label",
 								name, "cluster", "1", "value", 1, "group",
 								param, param + "Id", (long)m + 1));
 						source = i;
@@ -669,49 +683,29 @@
 					}
 					if (target == 0) {
 						String name = findTitleName(param, (long)n+1);
-						nodes.add(map7("id", i, "title", name, "label",
+						nodes.add(HashMapUtil.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"));
+					int zoom = 0;
+					if(param.equals("dataset")) {
+						zoom = 1600;
+					} else {
+						zoom = 6000;
+					}
+					rels.add(HashMapUtil.map6("from", source, "to", target, "title", "RELATE",
+							"id", edgeId, "weight", matrix[m][n], "length", zoom/matrix[m][n]));
+					edgeId ++;
 				}
 			}
 		}
 
-		return map("nodes", nodes, "edges", rels);
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
 	}
-
-	private Map<String, Object> map(String key1, Object value1, String key2,
-			Object value2) {
-		Map<String, Object> result = new HashMap<String, Object>(2);
-		result.put(key1, value1);
-		result.put(key2, value2);
-		return result;
-	}
-
-	private Map<String, Object> map3(String key1, Object value1, String key2,
-			Object value2, String key3, Object value3) {
-		Map<String, Object> result = new HashMap<String, Object>(3);
-		result.put(key1, value1);
-		result.put(key2, value2);
-		result.put(key3, value3);
-		return result;
-	}
-
-	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, String key7, Object value7) {
-		Map<String, Object> result = new HashMap<String, Object>(6);
-		result.put(key1, value1);
-		result.put(key2, value2);
-		result.put(key3, value3);
-		result.put(key4, value4);
-		result.put(key5, value5);
-		result.put(key6, value6);
-		result.put(key7, value7);
-		return result;
-	}
+	
+	private Sort sortByCountDesc() {
+        return new Sort(Sort.Direction.DESC, "count");
+    }
 }
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/DatasetLogController.java b/ApacheCMDA_Backend_1.0/app/controllers/DatasetLogController.java
index f92b68e..e53e197 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/DatasetLogController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/DatasetLogController.java
@@ -2,7 +2,14 @@
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
@@ -12,6 +19,7 @@
 import com.google.gson.Gson;
 
 import models.Dataset;
+import models.DatasetAndUser;
 import models.DatasetLog;
 import models.DatasetLogRepository;
 import models.DatasetRepository;
@@ -20,6 +28,7 @@
 import models.User;
 import models.UserRepository;
 import play.mvc.*;
+import util.HashMapUtil;
 
 @Named
 @Singleton
@@ -86,10 +95,13 @@
 			Dataset outputDataset = datasetRepository.findOne(outputDatasetId);
 			Dataset dataset = datasetRepository.findOne(datasetId);
 			ServiceExecutionLog serviceExecutionLog = serviceExecutionLogRepository.findOne(serviceExecutionLogId);
+			Date serviceExecutionStartTime = serviceExecutionLog.getExecutionStartTime();		
+			Date serviceExecutionEndTime = serviceExecutionLog.getExecutionEndTime();
 			User user = userRepository.findOne(userId);
 			DatasetLog datasetLog = new DatasetLog(serviceExecutionLog,
 					dataset, user, plotUrl, dataUrl, originalDataset,
-					outputDataset, datasetStudyStartTime, datasetStudyEndTime);
+					outputDataset, serviceExecutionStartTime, serviceExecutionEndTime,
+					datasetStudyStartTime, datasetStudyEndTime);
 			DatasetLog saveddatasetLog = datasetLogRepository.save(datasetLog);
 			System.out.println("DatasetLog saved: "+ saveddatasetLog.getId());
 			return created(new Gson().toJson(datasetLog.getId()));
@@ -206,5 +218,215 @@
     		return badRequest("DatasetLog not found");
     	}
     }
-	
+    
+    public Result queryDatasets() {
+    	JsonNode json = request().body().asJson();
+		Set<Dataset> datasets = new HashSet<Dataset>();
+		Map<String, Object> map = new HashMap<>();
+		
+		if (json == null) {
+			System.out.println("Dataset cannot be queried, expecting Json data");
+			String result = new Gson().toJson(map);
+			return ok(result);
+		}
+
+		try {
+			// Parse JSON file
+			Long userId = json.findPath("id").asLong();
+
+			Date start = new Date(0);
+			Date end = new Date();
+			long executionStartTimeNumber = json.findPath("executionStartTime")
+					.asLong();
+			long executionEndTimeNumber = json.findPath("executionEndTime")
+					.asLong();
+			
+			if (executionStartTimeNumber > 0) {
+				start = new Date(executionStartTimeNumber);
+			}
+			if (executionEndTimeNumber > 0) {
+				end = new Date(executionEndTimeNumber);
+			}
+			
+			List<DatasetLog> datasetLogs = datasetLogRepository.
+					findByServiceExecutionStartTimeGreaterThanEqualAndServiceExecutionEndTimeLessThanEqualAndUser_Id(start, end, userId);
+//			for (DatasetLog datasetLog : datasetLogs) {
+//				datasets.add(datasetLog.getDataset());
+//			}
+			map = jsonFormatUserAndDataset(datasetLogs);
+		} catch (Exception e) {
+			System.out.println("Dataset cannot be queried, query is corrupt");
+			String result = new Gson().toJson(map);
+			return ok(result);
+		}
+		
+		String result = new Gson().toJson(map);
+		return ok(result);
+    }
+    
+    private Map<String, Object> jsonFormatUserAndDataset(
+			Iterable<DatasetLog> userDatasets) {
+
+		List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+
+		int i = 1;
+		int edgeId = 1;
+		for (DatasetLog userDataset : userDatasets) {
+			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") == userDataset
+								.getUser().getId()) {
+					source = (int) nodes.get(j).get("id");
+					break;
+				}
+			}
+			if (source == 0) {
+				String realName = userDataset.getUser().getFirstName() + " "
+						+ userDataset.getUser().getLastName();
+				nodes.add(HashMapUtil.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("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(HashMapUtil.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(HashMapUtil.map5("from", source, "to", target, "title", "USE",
+					"id", edgeId, "weight", 0));
+			edgeId++;
+		}
+
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
+	}
+    
+    public Result queryVariables() {
+    	JsonNode json = request().body().asJson();
+		Set<Dataset> datasets = new HashSet<Dataset>();
+		Set<String> variables = new HashSet<String>();
+		Map<String, Object> map = new HashMap<>();
+		
+		if (json == null) {
+			System.out.println("Dataset cannot be queried, expecting Json data");
+			String result = new Gson().toJson(map);
+			return ok(result);
+		}
+
+		try {
+			// Parse JSON file
+			Long userId = json.findPath("userId").asLong();
+
+			Date start = new Date(0);
+			Date end = new Date();
+			long executionStartTimeNumber = json.findPath("executionStartTime")
+					.asLong();
+			long executionEndTimeNumber = json.findPath("executionEndTime")
+					.asLong();
+
+			if (executionStartTimeNumber > 0) {
+				start = new Date(executionStartTimeNumber);
+			}
+			if (executionEndTimeNumber > 0) {
+				end = new Date(executionEndTimeNumber);
+			}
+			
+			List<DatasetLog> datasetLogs = datasetLogRepository.
+					findByServiceExecutionStartTimeGreaterThanEqualAndServiceExecutionEndTimeLessThanEqualAndUser_Id(start, end, userId);
+			
+//			for (DatasetLog datasetLog : datasetLogs) {
+//				datasets.add(datasetLog.getDataset());
+//			}
+//			
+//			for (Dataset dataset : datasets) {
+//				variables.add(dataset.getPhysicalVariable());
+//			}
+			map = jsonFormatUserAndVariable(datasetLogs);
+			
+		} catch (Exception e) {
+			System.out.println("Dataset cannot be queried, query is corrupt");
+			String result = new Gson().toJson(map);
+			return ok(result);
+		}
+		
+		String result = new Gson().toJson(new ArrayList<String>(variables));
+		return ok(result);
+    }
+    
+    private Map<String, Object> jsonFormatUserAndVariable (
+			Iterable<DatasetLog> userDatasets) {
+
+		List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+		List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+
+		int i = 1;
+		int edgeId = 1;
+		for (DatasetLog userDataset : userDatasets) {
+			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") == userDataset
+								.getUser().getId()) {
+					source = (int) nodes.get(j).get("id");
+					break;
+				}
+			}
+			if (source == 0) {
+				String realName = userDataset.getUser().getFirstName() + " "
+						+ userDataset.getUser().getLastName();
+				nodes.add(HashMapUtil.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("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(HashMapUtil.map7("id", i, "title", userDataset.getDataset()
+						.getName(), "label",
+						userDataset.getDataset().getPhysicalVariable(), "cluster", "2",
+						"value", 2, "group", "dataset", "datasetId",
+						userDataset.getDataset().getId()));
+				target = i;
+				i++;
+			}
+			rels.add(HashMapUtil.map5("from", source, "to", target, "title", "USE",
+					"id", edgeId, "weight", 0));
+			edgeId++;
+		}
+
+		return HashMapUtil.map("nodes", nodes, "edges", rels);
+	}
 }
\ No newline at end of file
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/GraphAlgorithmController.java b/ApacheCMDA_Backend_1.0/app/controllers/GraphAlgorithmController.java
new file mode 100644
index 0000000..c240e5a
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/controllers/GraphAlgorithmController.java
@@ -0,0 +1,220 @@
+package controllers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jgrapht.GraphPath;
+import org.jgrapht.WeightedGraph;
+import org.jgrapht.alg.DijkstraShortestPath;
+import org.jgrapht.alg.KShortestPaths;
+import org.jgrapht.graph.DefaultWeightedEdge;
+import org.jgrapht.graph.SimpleWeightedGraph;
+
+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.HashMapUtil;
+import util.Matrix;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.Gson;
+
+@Named
+@Singleton
+public class GraphAlgorithmController 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 GraphAlgorithmController(
+			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 Result getShortestPath(int source, int target, String format) {
+		
+		try {
+			Iterable<DatasetAndUser> userDatasets = datasetAndUserRepository
+					.findAll();
+
+			if (userDatasets == null) {
+				System.out.println("User and Dataset: cannot be found!");
+				return notFound("User and Dataset: cannot be found!");
+			}
+			List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+			List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+			WeightedGraph<Integer, DefaultWeightedEdge> graph = createGraph(userDatasets, nodes, rels);
+			Map<String, Object> map = new HashMap<>();
+			
+			List<Map<String, Object>> node = new ArrayList<Map<String, Object>>();
+			List<Map<String, Object>> rel = new ArrayList<Map<String, Object>>();
+			
+			List<DefaultWeightedEdge> path =
+	                DijkstraShortestPath.findPathBetween(graph, source, target);
+			for(DefaultWeightedEdge p : path) {
+				int v1 = graph.getEdgeSource(p);
+				int v2 = graph.getEdgeTarget(p);
+				if(!node.contains(nodes.get(v1-1)))
+					node.add(nodes.get(v1-1));
+				if(!node.contains(nodes.get(v2-1)))
+					node.add(nodes.get(v2-1));
+				for(Map<String, Object> one : rels) {
+					if((int)one.get("from") == v1 && (int)one.get("to") == v2) {
+						rel.add(one);
+					}
+				}
+			}
+			
+			map = HashMapUtil.map("nodes", node, "edges", rel);
+			
+			String result = new String();
+			if (format.equals("json")) {
+				result = new Gson().toJson(map);
+			}
+
+			return ok(result);
+		} catch (Exception e) {
+			return badRequest(e.getMessage());
+		}
+	}
+	
+public Result getKShortestPath(int source, int target, int k, String format) {
+		
+		try {
+			Iterable<DatasetAndUser> userDatasets = datasetAndUserRepository
+					.findAll();
+
+			if (userDatasets == null) {
+				System.out.println("User and Dataset: cannot be found!");
+				return notFound("User and Dataset: cannot be found!");
+			}
+			List<Map<String, Object>> nodes = new ArrayList<Map<String, Object>>();
+			List<Map<String, Object>> rels = new ArrayList<Map<String, Object>>();
+			WeightedGraph<Integer, DefaultWeightedEdge> graph = createGraph(userDatasets, nodes, rels);
+			// return this map list
+			List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
+
+			KShortestPaths kPaths = new KShortestPaths(graph, source, k);
+			List<GraphPath> paths = kPaths.getPaths(target);
+	        
+			for(GraphPath p : paths) {
+				List<Map<String, Object>> node = new ArrayList<Map<String, Object>>();
+				List<Map<String, Object>> rel = new ArrayList<Map<String, Object>>();
+				for (Object edge : p.getEdgeList()) {
+					int v1 = graph.getEdgeSource((DefaultWeightedEdge)edge);
+					int v2 = graph.getEdgeTarget((DefaultWeightedEdge)edge);
+					if(!node.contains(nodes.get(v1-1)))
+						node.add(nodes.get(v1-1));
+					if(!node.contains(nodes.get(v2-1)))
+						node.add(nodes.get(v2-1));
+					for (Map<String, Object> one : rels) {
+						if((int)one.get("from") == v1 && (int)one.get("to") == v2) {
+							rel.add(one);
+						}
+					}
+				}
+				mapList.add(HashMapUtil.map("nodes", node, "edges", rel));
+			}
+		
+			String result = new String();
+			if (format.equals("json")) {
+				result = new Gson().toJson(mapList);
+			}
+
+			return ok(result);
+		} catch (Exception e) {
+			return badRequest(e.getMessage());
+		}
+	}
+	
+	public WeightedGraph<Integer, DefaultWeightedEdge> createGraph(Iterable<DatasetAndUser> userDatasets,
+			List<Map<String, Object>> nodes, List<Map<String, Object>> rels) {
+		WeightedGraph<Integer, DefaultWeightedEdge> g =
+	            new SimpleWeightedGraph<Integer, DefaultWeightedEdge>(DefaultWeightedEdge.class);
+
+		int i = 1;
+		long edgeId = 1;
+		for (DatasetAndUser userDataset : userDatasets) {
+			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") == userDataset
+								.getUser().getId()) {
+					source = (int) nodes.get(j).get("id");
+					break;
+				}
+			}
+			if (source == 0) {
+				String realName = userDataset.getUser().getFirstName() + " "
+						+ userDataset.getUser().getLastName();
+				nodes.add(HashMapUtil.map7("id", i, "title", realName, "label", userDataset
+						.getUser().getUserName(), "cluster", "1", "value", 1,
+						"group", "user", "userId", userDataset.getUser()
+								.getId()));
+
+				source = i;
+				g.addVertex(source);
+				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") == userDataset
+								.getDataset().getId()) {
+					target = (int) nodes.get(j).get("id");
+					break;
+				}
+			}
+			if (target == 0) {
+				nodes.add(HashMapUtil.map7("id", i, "title", userDataset.getDataset()
+						.getName(), "label",
+						userDataset.getDataset().getName(), "cluster", "2",
+						"value", 2, "group", "dataset", "datasetId",
+						userDataset.getDataset().getId()));
+				target = i;
+				g.addVertex(target);
+				i++;
+			}
+			rels.add(HashMapUtil.map5("from", source, "to", target, "title", "USE",
+					"id", edgeId, "weight", userDataset.getCount()));
+			g.addEdge(source, target);
+			g.setEdgeWeight(g.getEdge(source, target), userDataset.getCount());
+			edgeId++;
+		}
+		return g;
+	}
+
+}
diff --git a/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java b/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
index 9d5dad2..170ec78 100644
--- a/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
+++ b/ApacheCMDA_Backend_1.0/app/controllers/ServiceExecutionLogController.java
@@ -480,13 +480,14 @@
 					Dataset dataset = datasetRepository.findByDataSourceAndCMIP5VarName(source, variable).get(0);
 					DatasetLog datasetLog = new DatasetLog(savedServiceExecutionLog,
 							dataset, user, plotUrl, dataUrl, dataset,
-							dataset, datasetStudyStartTime, datasetStudyEndTime);
+							dataset, executionStartTime, executionEndTime,
+							datasetStudyStartTime, datasetStudyEndTime);
 					DatasetLog savedDatasetLog = datasetLogRepository.save(datasetLog);
 					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);
+						DatasetAndUser datasetAndUser = new DatasetAndUser(user, dataset, 1);
 						datasetAndUserRepository.save(datasetAndUser);
 					}
 					else {
diff --git a/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java b/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
index f6d8e27..d011cc0 100644
--- a/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/DatasetAndUserRepository.java
@@ -2,6 +2,7 @@
 
 import java.util.List;
 
+import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.CrudRepository;
 
 import javax.inject.Named;
@@ -14,4 +15,5 @@
 	List<DatasetAndUser> findByUserAndDataset(User user, Dataset dataset);
 	List<DatasetAndUser> findByUser(User user);
 	List<DatasetAndUser> findByDataset(Dataset dataset);
+	List<DatasetAndUser> findAll(Sort sort);
 }
diff --git a/ApacheCMDA_Backend_1.0/app/models/DatasetLog.java b/ApacheCMDA_Backend_1.0/app/models/DatasetLog.java
index b3a1069..ac92a53 100644
--- a/ApacheCMDA_Backend_1.0/app/models/DatasetLog.java
+++ b/ApacheCMDA_Backend_1.0/app/models/DatasetLog.java
@@ -8,9 +8,12 @@
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
 
 @Entity
 public class DatasetLog {
+	
 	@Id
 	@GeneratedValue(strategy = GenerationType.AUTO)
 	private long id;
@@ -32,6 +35,11 @@
 	@JoinColumn(name = "outputDatasetId", referencedColumnName = "id")
 	private Dataset outputDataset;
 	
+	@Temporal(TemporalType.TIMESTAMP)
+	private Date serviceExecutionStartTime;
+	@Temporal(TemporalType.TIMESTAMP)
+	private Date serviceExecutionEndTime;
+	
 	private Date datasetStudyStartTime;
 	private Date datasetStudyEndTime;
 	
@@ -39,9 +47,11 @@
 		
 	}
 	
-	public DatasetLog(ServiceExecutionLog serviceExecutionLog, Dataset dataset,
-			User user, String plotUrl, String dataUrl, Dataset originalDataset,
-			Dataset outputDataset, Date datasetStudyStartTime, Date datasetStudyEndTime) {
+	public DatasetLog(ServiceExecutionLog serviceExecutionLog,
+			Dataset dataset, User user, String plotUrl, String dataUrl,
+			Dataset originalDataset, Dataset outputDataset,
+			Date serviceExecutionStartTime, Date serviceExecutionEndTime,
+			Date datasetStudyStartTime, Date datasetStudyEndTime) {
 		super();
 		this.serviceExecutionLog = serviceExecutionLog;
 		this.dataset = dataset;
@@ -50,6 +60,8 @@
 		this.dataUrl = dataUrl;
 		this.originalDataset = originalDataset;
 		this.outputDataset = outputDataset;
+		this.serviceExecutionStartTime = serviceExecutionStartTime;
+		this.serviceExecutionEndTime = serviceExecutionEndTime;
 		this.datasetStudyStartTime = datasetStudyStartTime;
 		this.datasetStudyEndTime = datasetStudyEndTime;
 	}
@@ -118,6 +130,22 @@
 		this.user = user;
 	}
 	
+	public Date getServiceExecutionStartTime() {
+		return serviceExecutionStartTime;
+	}
+
+	public void setServiceExecutionStartTime(Date serviceExecutionStartTime) {
+		this.serviceExecutionStartTime = serviceExecutionStartTime;
+	}
+
+	public Date getServiceExecutionEndTime() {
+		return serviceExecutionEndTime;
+	}
+
+	public void setServiceExecutionEndTime(Date serviceExecutionEndTime) {
+		this.serviceExecutionEndTime = serviceExecutionEndTime;
+	}
+	
 	public Date getDatasetStudyStartTime() {
 		return datasetStudyStartTime;
 	}
@@ -137,13 +165,14 @@
 	@Override
 	public String toString() {
 		return "DatasetLog [id=" + id + ", serviceExecutionLog="
-				+ serviceExecutionLog + ", dataSet=" + dataset + ", user="
+				+ serviceExecutionLog + ", dataset=" + dataset + ", user="
 				+ user + ", plotUrl=" + plotUrl + ", dataUrl=" + dataUrl
-				+ ", originalDataSet=" + originalDataset + ", outputDataSet="
-				+ outputDataset + ", datasetStudyStartTime="
+				+ ", originalDataset=" + originalDataset + ", outputDataset="
+				+ outputDataset + ", serviceExecutionStartTime="
+				+ serviceExecutionStartTime + ", serviceExecutionEndTime="
+				+ serviceExecutionEndTime + ", datasetStudyStartTime="
 				+ datasetStudyStartTime + ", datasetStudyEndTime="
 				+ datasetStudyEndTime + "]";
 	}
 	
-	
 }
diff --git a/ApacheCMDA_Backend_1.0/app/models/DatasetLogRepository.java b/ApacheCMDA_Backend_1.0/app/models/DatasetLogRepository.java
index de4ce6c..83068f8 100644
--- a/ApacheCMDA_Backend_1.0/app/models/DatasetLogRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/DatasetLogRepository.java
@@ -1,5 +1,8 @@
 package models;
 
+import java.util.Date;
+import java.util.List;
+
 import org.springframework.data.repository.CrudRepository;
 
 import javax.inject.Named;
@@ -9,4 +12,6 @@
 @Singleton
 public interface DatasetLogRepository extends CrudRepository<DatasetLog, Long> {
 	
+    List<DatasetLog> findByServiceExecutionStartTimeGreaterThanEqualAndServiceExecutionEndTimeLessThanEqualAndUser_Id(Date serviceExecutionStartTime, Date serviceExecutionEndTime, long userId);
+
 }
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java
index 14258b3..a9c67b1 100644
--- a/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndDatasetRepository.java
@@ -2,6 +2,7 @@
 
 import java.util.List;
 
+import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.CrudRepository;
 
 import javax.inject.Named;
@@ -13,6 +14,6 @@
 
 	List<ServiceAndDataset> findByClimateService(ClimateService service);
 	List<ServiceAndDataset> findByDataset(Dataset dataset);
-		
+	List<ServiceAndDataset> findAll(Sort sort);
 }
 
diff --git a/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java
index 4f1c960..deb319c 100644
--- a/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java
+++ b/ApacheCMDA_Backend_1.0/app/models/ServiceAndUserRepository.java
@@ -2,6 +2,7 @@
 
 import java.util.List;
 
+import org.springframework.data.domain.Sort;
 import org.springframework.data.repository.CrudRepository;
 
 import javax.inject.Named;
@@ -13,6 +14,6 @@
 
 	List<ServiceAndUser> findByUser(User user);
 	List<ServiceAndUser> findByClimateService(ClimateService service);
-		
+	List<ServiceAndUser> findAll(Sort sort);
 }
 
diff --git a/ApacheCMDA_Backend_1.0/app/util/HashMapUtil.java b/ApacheCMDA_Backend_1.0/app/util/HashMapUtil.java
new file mode 100644
index 0000000..3f03084
--- /dev/null
+++ b/ApacheCMDA_Backend_1.0/app/util/HashMapUtil.java
@@ -0,0 +1,55 @@
+package util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class HashMapUtil {
+	
+	public static Map<String, Object> map(String key1, Object value1, String key2,
+			Object value2) {
+		Map<String, Object> result = new HashMap<String, Object>(2);
+		result.put(key1, value1);
+		result.put(key2, value2);
+		return result;
+	}
+	
+	public static Map<String, Object> map5(String key1, Object value1, String key2,
+			Object value2, String key3, Object value3, String key4, Object value4,
+			String key5, Object value5) {
+		Map<String, Object> result = new HashMap<String, Object>(5);
+		result.put(key1, value1);
+		result.put(key2, value2);
+		result.put(key3, value3);
+		result.put(key4, value4);
+		result.put(key5, value5);
+		return result;
+	}
+	
+	public static Map<String, Object> map6(String key1, Object value1, String key2,
+			Object value2, String key3, Object value3, String key4, Object value4,
+			String key5, Object value5, String key6, Object value6) {
+		Map<String, Object> result = new HashMap<String, Object>(6);
+		result.put(key1, value1);
+		result.put(key2, value2);
+		result.put(key3, value3);
+		result.put(key4, value4);
+		result.put(key5, value5);
+		result.put(key6, value6);
+		return result;
+	}
+
+	public static 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, String key7, Object value7) {
+		Map<String, Object> result = new HashMap<String, Object>(7);
+		result.put(key1, value1);
+		result.put(key2, value2);
+		result.put(key3, value3);
+		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/build.sbt b/ApacheCMDA_Backend_1.0/build.sbt
index e1d17a5..c5101a8 100644
--- a/ApacheCMDA_Backend_1.0/build.sbt
+++ b/ApacheCMDA_Backend_1.0/build.sbt
@@ -20,7 +20,7 @@
   "org.mockito" % "mockito-core" % "1.10.19" % "test",
   "mysql" % "mysql-connector-java" % "5.1.34",
   "com.google.code.gson" % "gson" % "2.3.1",
-  "org.hibernate" % "hibernate-c3p0" % "4.3.7.Final"
+  "org.hibernate" % "hibernate-c3p0" % "4.3.7.Final",
+  "com.googlecode.efficient-java-matrix-library" % "ejml" % "0.23",
+  "org.jgrapht" % "jgrapht-jdk1.5" % "0.7.3"
 )
-
-
diff --git a/ApacheCMDA_Backend_1.0/conf/.DS_Store b/ApacheCMDA_Backend_1.0/conf/.DS_Store
index c7bbec7..5008ddf 100644
--- a/ApacheCMDA_Backend_1.0/conf/.DS_Store
+++ 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 3846661..46b5ef1 100644
--- a/ApacheCMDA_Backend_1.0/conf/routes
+++ b/ApacheCMDA_Backend_1.0/conf/routes
@@ -64,6 +64,8 @@
 GET           /datasetLog/getAllDatasetLogs/json                                                        @controllers.DatasetLogController.getAllDatasetLogs(format: String="json")
 GET           /datasetLog/getDatasetLog/id/:id/json                                                     @controllers.DatasetLogController.getDatasetLog(id: Long, format: String="json")
 POST          /datasetLog/addDatasetLog                                                                 @controllers.DatasetLogController.addDatasetLog
+POST		  /datasetLog/queryDatasets																	@controllers.DatasetLogController.queryDatasets
+POST		  /datasetLog/queryVariables																@controllers.DatasetLogController.queryVariables
 PUT           /datasetLog/updateDatasetLog/id/:id                                                       @controllers.DatasetLogController.updateDatasetLogById(id: Long)
 DELETE        /datasetLog/deleteDatasetLog/id/:id                                                       @controllers.DatasetLogController.deleteDatasetLog(id: Long)
 
@@ -139,16 +141,20 @@
 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/getAllServiceAndUserWithCount/json											    @controllers.AnalyticsController.getAllServiceAndUserWithCount(format: String="json")
-#GET			  /analytics/getAllServiceAndDatasetWithCount/json											@controllers.AnalyticsController.getAllServiceAndDatasetWithCount(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/getOneDatasetWithAllUserAndCountByDatasetId/:id/json							@controllers.AnalyticsController.getOneDatasetWithAllUserAndCount(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")
 
+# Graph Algorithm
+GET			  /graphAlgorithm/getShortestPath/source/:source/target/:target/json						@controllers.GraphAlgorithmController.getShortestPath(source: Integer, target: Integer, format: String="json")
+GET			  /graphAlgorithm/getKthShortestPath/source/:source/target/:target/k/:k/json				@controllers.GraphAlgorithmController.getKShortestPath(source: Integer, target: Integer, k:Integer, format: String="json")
+
 # Map static resources from the /public folder to the /assets URL path
 GET           /assets/*file                                                                             controllers.Assets.at(path="/public", file)
diff --git a/ApacheCMDA_Backend_1.0/test/DatasetLogTest.java b/ApacheCMDA_Backend_1.0/test/DatasetLogTest.java
index eb5f371..21e4960 100644
--- a/ApacheCMDA_Backend_1.0/test/DatasetLogTest.java
+++ b/ApacheCMDA_Backend_1.0/test/DatasetLogTest.java
@@ -20,6 +20,8 @@
 	private static Dataset TEST_ORIGINAL_DATASET;
 	private static Dataset TEST_OUTPUT_DATASET;
 	private static User TEST_USER;
+	private static Date TEST_SERVICE_EXECUTION_START_TIME;
+	private static Date TEST_SERVICE_EXECUTION_END_TIME;
 	private static Date TEST_DATASET_STUDY_START_TIME;
 	private static Date TEST_DATASET_STUDY_END_TIME;
 	
@@ -34,10 +36,13 @@
 		TEST_OUTPUT_DATASET = new Dataset();
 		datasetLog = new DatasetLog();
 		TEST_USER = new User();
+		TEST_SERVICE_EXECUTION_START_TIME = new Date();
+		TEST_SERVICE_EXECUTION_END_TIME = new Date();
 		TEST_DATASET_STUDY_START_TIME = new Date();
 		TEST_DATASET_STUDY_END_TIME = new Date();
 		datasetLog1 = new DatasetLog(serviceExecutionLog, TEST_DATASET, TEST_USER, TEST_PLOT_URL, TEST_DATA_URL,
-				TEST_ORIGINAL_DATASET, TEST_OUTPUT_DATASET, TEST_DATASET_STUDY_START_TIME, TEST_DATASET_STUDY_END_TIME);
+				TEST_ORIGINAL_DATASET, TEST_OUTPUT_DATASET, TEST_SERVICE_EXECUTION_START_TIME, TEST_SERVICE_EXECUTION_END_TIME,
+				TEST_DATASET_STUDY_START_TIME, TEST_DATASET_STUDY_END_TIME);
 	}
 	
 	@Test
diff --git a/ApacheCMDA_Backend_1.0/test/ServiceExecutionLogTest.java b/ApacheCMDA_Backend_1.0/test/ServiceExecutionLogTest.java
index f237e96..8642767 100644
--- a/ApacheCMDA_Backend_1.0/test/ServiceExecutionLogTest.java
+++ b/ApacheCMDA_Backend_1.0/test/ServiceExecutionLogTest.java
@@ -25,6 +25,7 @@
 	private static String TEST_DATA_URL = "test_dataUrl";
 	private static Date TEST_DATASET_STUDY_START_TIME;
 	private static Date TEST_DATASET_STUDY_END_TIME;
+	private static String TEST_URL = "test_url";
 	
 	private static ServiceExecutionLog serviceExecutionLog;
 	private static ServiceExecutionLog serviceExecutionLog1;
@@ -41,7 +42,7 @@
 		TEST_DATASET_STUDY_END_TIME = new Date();
 		serviceExecutionLog1 = new ServiceExecutionLog(climateService, user, serviceConfiguration, TEST_PURPOSE,
 				TEST_EXECUTION_START_TIME, TEST_EXECUTION_END_TIME, TEST_DATA_URL, TEST_PLOT_URL,
-				TEST_DATASET_STUDY_START_TIME, TEST_DATASET_STUDY_END_TIME);
+				TEST_DATASET_STUDY_START_TIME, TEST_DATASET_STUDY_END_TIME, TEST_URL);
 	}
 	
 	@Test
@@ -99,6 +100,12 @@
 	}
 	
 	@Test
+	public void testUrl(){
+		serviceExecutionLog.setUrl(TEST_URL);
+		assertEquals(TEST_URL, serviceExecutionLog.getUrl());
+	}
+	
+	@Test
 	public void testDatasetStudyStartTime() {
 		serviceExecutionLog.setDatasetStudyStartTime(TEST_DATASET_STUDY_START_TIME);
 		assertEquals(TEST_DATASET_STUDY_START_TIME, serviceExecutionLog.getDatasetStudyStartTime());