You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cmda.apache.org by xi...@apache.org on 2015/09/09 00:49:47 UTC

[38/51] [partial] incubator-cmda git commit: Add frontend and backend

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/controllers/ServiceExecutionLogController.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/controllers/ServiceExecutionLogController.java b/ApacheCMDA-Backend/app/controllers/ServiceExecutionLogController.java
new file mode 100644
index 0000000..598e2f5
--- /dev/null
+++ b/ApacheCMDA-Backend/app/controllers/ServiceExecutionLogController.java
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package controllers;
+
+import java.util.*;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.persistence.PersistenceException;
+
+import models.ClimateService;
+import models.ClimateServiceRepository;
+import models.Dataset;
+import models.DatasetEntry;
+import models.DatasetEntryRepository;
+//import models.DatasetLog;
+import models.DatasetLogRepository;
+import models.DatasetRepository;
+import models.Parameter;
+import models.ParameterRepository;
+import models.ServiceConfiguration;
+import models.ServiceConfigurationItem;
+import models.ServiceConfigurationItemRepository;
+import models.ServiceConfigurationRepository;
+import models.ServiceEntry;
+import models.ServiceEntryRepository;
+import models.ServiceExecutionLog;
+import models.ServiceExecutionLogRepository;
+import models.User;
+import models.UserRepository;
+import play.libs.F;
+import play.mvc.Controller;
+import play.mvc.Result;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.Gson;
+
+/**
+ * The main set of web services.
+ */
+@Named
+@Singleton
+public class ServiceExecutionLogController extends Controller {
+	public static final String WILDCARD = "%";
+
+	private final DatasetRepository datasetRepository;
+	private final DatasetEntryRepository datasetEntryRepository;
+	private final ServiceExecutionLogRepository serviceExecutionLogRepository;
+	private final ServiceEntryRepository serviceEntryRepository;
+	private final UserRepository userRepository;
+	private final ClimateServiceRepository climateServiceRepository;
+	private final ParameterRepository parameterRepository;
+	private final ServiceConfigurationItemRepository serviceConfigurationItemRepository;
+	// private final DatasetLogRepository datasetLogRepository;
+	private final ServiceConfigurationRepository serviceConfigurationRepository;
+
+	// We are using constructor injection to receive a repository to support our
+	// desire for immutability.
+	@Inject
+	public ServiceExecutionLogController(
+			ServiceExecutionLogRepository serviceExecutionLogRepository,
+			ParameterRepository parameterRepository,
+			ServiceConfigurationItemRepository serviceConfigurationItemRepository,
+			UserRepository userRepository,
+			ClimateServiceRepository climateServiceRepository,
+			DatasetLogRepository datasetLogRepository,
+			ServiceConfigurationRepository serviceConfigurationRepository,
+			ServiceEntryRepository serviceEntryRepository,
+			DatasetEntryRepository datasetEntryRepository,
+			DatasetRepository datasetRepository) {
+		this.parameterRepository = parameterRepository;
+		this.serviceExecutionLogRepository = serviceExecutionLogRepository;
+		this.userRepository = userRepository;
+		this.serviceConfigurationItemRepository = serviceConfigurationItemRepository;
+		this.climateServiceRepository = climateServiceRepository;
+		// this.datasetLogRepository = datasetLogRepository;
+		this.serviceConfigurationRepository = serviceConfigurationRepository;
+		this.serviceEntryRepository = serviceEntryRepository;
+		this.datasetEntryRepository = datasetEntryRepository;
+		this.datasetRepository = datasetRepository;
+	}
+
+	public Result queryServiceExecutionLogs() {
+		// JsonNode json = request().body().asJson();
+		// if (json == null) {
+		// System.out
+		// .println("ServiceExecutionLog cannot be queried, expecting Json data");
+		// return
+		// badRequest("ServiceExecutionLog cannot be queried, expecting Json data");
+		// }
+		// String result = new String();
+		//
+		// try {
+		// // Parse JSON file
+		// Long userId = json.findPath("userId").asLong();
+		// // long datasetLogId = json.findPath("datasetLogId").asLong();
+		// String purpose = json.findPath("purpose").asText();
+		// if (purpose.isEmpty()) {
+		// purpose = WILDCARD;
+		// } else {
+		// purpose = WILDCARD + purpose + WILDCARD;
+		// }
+		//
+		// 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);
+		// }
+		//
+		// // If we change the date format later, we can modify here.
+		// //
+		// // String executionStartTimeString =
+		// // json.findPath("executionStartTime").asText();
+		// // String executionEndTimeString =
+		// // json.findPath("executionEndTime").asText();
+		// // SimpleDateFormat simpleDateFormat = new
+		// // SimpleDateFormat(util.Common.DATE_PATTERN);
+		// //
+		// // try {
+		// // executionStartTime =
+		// // simpleDateFormat.parse(executionStartTimeString);
+		// // } catch (ParseException e) {
+		// // // TODO Auto-generated catch block
+		// // e.printStackTrace();
+		// // System.out.println("Wrong Date Format :" +
+		// // executionStartTimeString);
+		// // return badRequest("Wrong Date Format :" +
+		// // executionStartTimeString);
+		// // }
+		// // try {
+		// // executionEndTime =
+		// // simpleDateFormat.parse(executionEndTimeString);
+		// // } catch (ParseException e) {
+		// // // TODO Auto-generated catch block
+		// // e.printStackTrace();
+		// // System.out.println("Wrong Date Format :" +
+		// // executionEndTimeString);
+		// // return badRequest("Wrong Date Format :" +
+		// // executionEndTimeString);
+		// // }
+		//
+		// JsonNode parameters = json.findPath("parameters");
+		// Iterator<String> iterator = parameters.fieldNames();
+		// List<ServiceExecutionLog> logs;
+		// if (!iterator.hasNext()) {
+		// if (userId != 0) {
+		// logs = serviceExecutionLogRepository
+		// .findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndUser_Id(
+		// start, end, purpose, userId);
+		// } else {
+		// logs = serviceExecutionLogRepository
+		// .findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLike(
+		// start, end, purpose);
+		// }
+		// } else {
+		// Set<ServiceConfiguration> configurationsSet = null;
+		// while (iterator.hasNext()) {
+		// String parameterName = iterator.next();
+		// String value = parameters.findPath(parameterName).asText();
+		// if (value != null && !value.isEmpty()) {
+		// List<Parameter> parameterList = parameterRepository
+		// .findByName(parameterName);
+		// // Find the serviceConfigurationItems that match the
+		// // parameters
+		// // If parameter is not ranged
+		// List<ServiceConfigurationItem> serviceConfigurationItem =
+		// serviceConfigurationItemRepository
+		// .findByParameterInAndValue(parameterList, value);
+		// Set<ServiceConfiguration> tempConfigSet = new
+		// HashSet<ServiceConfiguration>();
+		//
+		// for (ServiceConfigurationItem items : serviceConfigurationItem) {
+		// tempConfigSet.add(items.getServiceConfiguration());
+		// }
+		//
+		// configurationsSet = intersectServiceConfiguration(
+		// configurationsSet, tempConfigSet);
+		// }
+		// }
+		//
+		// // DatasetLog datasetLog =
+		// // datasetLogRepository.findOne(datasetLogId);
+		//
+		// if (configurationsSet == null || configurationsSet.isEmpty()) {
+		// // If no parameter matches, just return the empty set
+		// logs = new ArrayList<ServiceExecutionLog>();
+		// } else {
+		// if (userId != 0) {
+		// logs = serviceExecutionLogRepository
+		// .findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndUser_IdAndServiceConfigurationIn(
+		// start, end, purpose, userId,
+		// configurationsSet);
+		// } else {
+		// logs = serviceExecutionLogRepository
+		// .findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndServiceConfigurationIn(
+		// start, end, purpose, configurationsSet);
+		// }
+		// }
+		// }
+		// result = new Gson().toJson(logs);
+		// } catch (Exception e) {
+		// System.out
+		// .println("ServiceExecutionLog cannot be queried, query is corrupt");
+		// return
+		// badRequest("ServiceExecutionLog cannot be queried, query is corrupt");
+		// }
+		//
+		// return ok(result);
+
+		List<ServiceExecutionLog> logs = queryServiceExecutionLogsAsList();
+		String result = new Gson().toJson(logs);
+		return ok(result);
+	}
+
+	public List<ServiceExecutionLog> queryServiceExecutionLogsAsList() {
+		JsonNode json = request().body().asJson();
+		List<ServiceExecutionLog> logs = null;
+		if (json == null) {
+			System.out
+					.println("ServiceExecutionLog cannot be queried, expecting Json data");
+			return logs;
+		}
+
+		try {
+			// Parse JSON file
+			Long userId = json.findPath("userId").asLong();
+			// long datasetLogId = json.findPath("datasetLogId").asLong();
+			String purpose = json.findPath("purpose").asText();
+			if (purpose.isEmpty()) {
+				purpose = WILDCARD;
+			} else {
+				purpose = WILDCARD + purpose + WILDCARD;
+			}
+
+			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);
+			}
+
+			JsonNode parameters = json.findPath("parameters");
+			Iterator<String> iterator = parameters.fieldNames();
+			if (!iterator.hasNext()) {
+				if (userId != 0) {
+					logs = serviceExecutionLogRepository
+							.findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndUser_Id(
+									start, end, purpose, userId);
+				} else {
+					logs = serviceExecutionLogRepository
+							.findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLike(
+									start, end, purpose);
+				}
+			} else {
+				Set<ServiceConfiguration> configurationsSet = null;
+				while (iterator.hasNext()) {
+					String parameterName = iterator.next();
+					String value = parameters.findPath(parameterName).asText();
+					if (value != null && !value.isEmpty()) {
+						List<Parameter> parameterList = parameterRepository
+								.findByName(parameterName);
+						// Find the serviceConfigurationItems that match the
+						// parameters
+						// If parameter is not ranged
+						List<ServiceConfigurationItem> serviceConfigurationItem = serviceConfigurationItemRepository
+								.findByParameterInAndValue(parameterList, value);
+						Set<ServiceConfiguration> tempConfigSet = new HashSet<ServiceConfiguration>();
+
+						for (ServiceConfigurationItem items : serviceConfigurationItem) {
+							tempConfigSet.add(items.getServiceConfiguration());
+						}
+
+						configurationsSet = intersectServiceConfiguration(
+								configurationsSet, tempConfigSet);
+					}
+				}
+
+				if (configurationsSet == null || configurationsSet.isEmpty()) {
+					// If no parameter matches, just return the empty set
+					logs = new ArrayList<ServiceExecutionLog>();
+				} else {
+					if (userId != 0) {
+						logs = serviceExecutionLogRepository
+								.findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndUser_IdAndServiceConfigurationIn(
+										start, end, purpose, userId,
+										configurationsSet);
+					} else {
+						logs = serviceExecutionLogRepository
+								.findByExecutionStartTimeGreaterThanEqualAndExecutionEndTimeLessThanEqualAndPurposeLikeAndServiceConfigurationIn(
+										start, end, purpose, configurationsSet);
+					}
+				}
+			}
+		} catch (Exception e) {
+			System.out
+					.println("ServiceExecutionLog cannot be queried, query is corrupt");
+			return logs;
+		}
+
+		return logs;
+	}
+
+	private Set<ServiceConfiguration> intersectServiceConfiguration(
+			Set<ServiceConfiguration> configurationsSet,
+			Set<ServiceConfiguration> tempConfigSet) {
+		if (configurationsSet == null) {
+			configurationsSet = tempConfigSet;
+		} else {
+			configurationsSet.retainAll(tempConfigSet);
+		}
+		return configurationsSet;
+	}
+
+	public Result addServiceExecutionLog() {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out
+					.println("ServiceExecutionLog not saved, expecting Json data");
+			return badRequest("ServiceExecutionLog not saved, expecting Json data");
+		}
+
+		// Parse JSON file
+		long serviceId = json.findPath("serviceId").asLong();
+		long userId = json.findPath("userId").asLong();
+		// long datasetLogId = json.findPath("datasetLogId").asLong();
+		String purpose = json.findPath("purpose").asText();
+		String plotUrl = json.findPath("url").asText();
+		String dataUrl = json.findPath("dataUrl").asText();
+
+		SimpleDateFormat formatter = new SimpleDateFormat(util.Common.DATE_PATTERN);
+		formatter.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+		
+		long executionStartTimeNumber = json.findPath("executionStartTime")
+				.asLong();
+		long executionEndTimeNumber = json.findPath("executionEndTime")
+				.asLong();
+		String executionStartTimeStr = formatter.format(new Date(executionStartTimeNumber));
+		String executionEndTimeStr = formatter.format(new Date(executionEndTimeNumber));
+		
+		Date executionStartTime = new Date();
+		Date executionEndTime = new Date();;
+		try {
+			executionStartTime = formatter.parse(executionStartTimeStr);
+			executionEndTime = formatter.parse(executionEndTimeStr);
+		} catch (ParseException e1) {
+			// TODO Auto-generated catch block
+			e1.printStackTrace();
+		}
+		
+		
+		String datasetStudyStartTimeNumber = json.findPath("datasetStudyStartTime")
+				.asText();
+		String datasetStudyEndTimeNumber = json.findPath("datasetStudyEndTime")
+				.asText();
+		Date datasetStudyStartTime = new Date();
+		Date datasetStudyEndTime = new Date();
+
+		// If we change the date format later, we can modify here.
+		//
+		 SimpleDateFormat simpleDateFormat = new SimpleDateFormat(util.Common.DATASET_DATE_PATTERN);
+		 
+		 try {
+			 datasetStudyStartTime = simpleDateFormat.parse(datasetStudyStartTimeNumber);
+			 datasetStudyEndTime = simpleDateFormat.parse(datasetStudyEndTimeNumber);
+		 
+		 } catch (ParseException e) {
+		 // TODO Auto-generated catch block
+		 e.printStackTrace();
+		 System.out.println("Wrong Date Format :" + datasetStudyStartTime + " " +datasetStudyEndTime);
+		 return badRequest("Wrong Date Format :" + datasetStudyStartTime + " " +datasetStudyEndTime);
+		 }
+//		 try {
+//		 executionEndTime = simpleDateFormat.parse(executionEndTimeString);
+//		 } catch (ParseException e) {
+//		 // TODO Auto-generated catch block
+//		 e.printStackTrace();
+//		 System.out.println("Wrong Date Format :" + executionEndTimeString);
+//		 return badRequest("Wrong Date Format :" + executionEndTimeString);
+//		 }
+
+		try {
+			User user = userRepository.findOne(userId);
+			ClimateService climateService = climateServiceRepository
+					.findOne(serviceId);
+			List<ServiceEntry> serviceEntries = serviceEntryRepository
+					.findByClimateServiceAndVersionNo(climateService,
+							climateService.getVersionNo());
+			ServiceEntry serviceEntry = null;
+			if (serviceEntries.size() == 0) {
+				String registerNote = "ClimateService Name: "
+						+ climateService.getName() + ", VersionNo: "
+						+ climateService.getVersionNo();
+				serviceEntry = new ServiceEntry(climateService.getCreateTime(),
+						climateService.getVersionNo(),
+						climateService.getUser(),
+						climateService.getCreateTime(), registerNote, 0,
+						climateService);
+			} else {
+				serviceEntry = serviceEntries.get(0);
+			}
+			long difference = executionEndTime.getTime()
+					- executionStartTime.getTime();
+			ServiceConfiguration serviceConfiguration = new ServiceConfiguration(
+					climateService, user, difference + "ms");
+			ServiceExecutionLog serviceExecutionLog = new ServiceExecutionLog(
+					climateService, user, serviceConfiguration, purpose,
+					executionStartTime, executionEndTime, dataUrl, plotUrl,
+					datasetStudyStartTime, datasetStudyEndTime);
+			ServiceExecutionLog savedServiceExecutionLog = serviceExecutionLogRepository
+					.save(serviceExecutionLog);
+			ServiceConfiguration savedServiceConfiguration = savedServiceExecutionLog
+					.getServiceConfiguration();
+			User admin = userRepository.findOne((long) 1);
+			JsonNode parameters = json.findPath("parameters");
+			Iterator<String> iterator = parameters.fieldNames();
+			while (iterator.hasNext()) {
+				String fieldName = iterator.next();
+				String value = parameters.findPath(fieldName).asText();
+				if (fieldName.equals("model") || fieldName.equals("model1")
+						|| fieldName.equals("model2")) {
+					List<Dataset> datasets = datasetRepository
+							.findByvariableNameInWebInterface(value);
+					if (datasets.size() != 0) {
+						Dataset dataset = datasets.get(0);
+						List<DatasetEntry> datasetEntries = datasetEntryRepository
+								.findByDataset(dataset);
+						DatasetEntry updateDatasetEntry = new DatasetEntry();
+						if (datasetEntries.size() != 0) {
+							updateDatasetEntry = datasetEntries.get(0);
+							int count = updateDatasetEntry.getCount();
+							updateDatasetEntry.setCount(count + 1);
+							updateDatasetEntry.setLatestAccessTimeStamp(new Date());
+						} else {
+							updateDatasetEntry = new DatasetEntry( "1.0", new Date(),
+									"Dataset Name:" + dataset.getVariableNameInWebInterface()
+									+ " VersionNo: 1.0", 1, new Date(), dataset, admin);
+						}
+						DatasetEntry savedDatasetEntry = datasetEntryRepository
+								.save(updateDatasetEntry);
+						System.out.print("DatasetEntry saved:"
+								+ savedDatasetEntry.getId());
+					}
+				}
+				Parameter parameter = parameterRepository
+						.findByNameAndClimateService(fieldName, climateService);
+				ServiceConfigurationItem serviceConfigurationItem = new ServiceConfigurationItem(
+						savedServiceConfiguration, parameter, value);
+				ServiceConfigurationItem savedServiceConfigurationItem = serviceConfigurationItemRepository
+						.save(serviceConfigurationItem);
+				System.out.println("ServiceConfigurationItem saved: "
+						+ savedServiceConfigurationItem.getId());
+			}
+			serviceEntry.setCount(serviceEntry.getCount() + 1);
+			serviceEntry.setLatestAccessTimestamp(new Date());
+			ServiceEntry savedServiceEntry = serviceEntryRepository
+					.save(serviceEntry);
+			System.out.println("ServiceExecutionLog saved: "
+					+ savedServiceEntry.getId());
+			return created(new Gson().toJson(savedServiceExecutionLog.getId()));
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println(pe.getClass().toString());
+			System.out.println("ServiceExecutionLog not saved");
+			return badRequest("ServiceExecutionLog not saved");
+		}
+	}
+
+	public Result deleteServiceExecutionLog(Long id) {
+		ServiceExecutionLog serviceExecutionLog = serviceExecutionLogRepository
+				.findOne(id);
+		if (serviceExecutionLog == null) {
+			System.out.println("ServiceExecutionLog not found with id: " + id);
+			return notFound("ServiceExecutionLog not found with id: " + id);
+		}
+
+		for (ServiceConfigurationItem items : serviceConfigurationItemRepository
+				.findByServiceConfiguration_Id(serviceExecutionLog
+						.getServiceConfiguration().getId())) {
+			serviceConfigurationItemRepository.delete(items.getId());
+		}
+		serviceExecutionLogRepository.delete(serviceExecutionLog);
+		System.out.println("ServiceExecutionLog is deleted: " + id);
+		return ok("ServiceExecutionLog is deleted: " + id);
+	}
+
+	public Result updateServiceExecutionLog(long id) {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out
+					.println("ServiceExecutionLog not saved, expecting Json data");
+			return badRequest("ServiceExecutionLog not saved, expecting Json data");
+		}
+
+		// Parse JSON file
+		long serviceId = json.findPath("serviceId").asLong();
+		long userId = json.findPath("userId").asLong();
+		String purpose = json.findPath("purpose").asText();
+		String plotUrl = json.findPath("url").asText();
+		String dataUrl = json.findPath("dataUrl").asText();
+		long executionStartTimeNumber = json.findPath("executionStartTime")
+				.asLong();
+		long executionEndTimeNumber = json.findPath("executionEndTime")
+				.asLong();
+		Date executionStartTime = new Date(executionStartTimeNumber);
+		Date executionEndTime = new Date(executionEndTimeNumber);
+
+		try {
+			User user = userRepository.findOne(userId);
+			ClimateService climateService = climateServiceRepository
+					.findOne(serviceId);
+			ServiceExecutionLog serviceExecutionLog = serviceExecutionLogRepository
+					.findOne(id);
+			ServiceConfiguration serviceConfiguration = serviceExecutionLog
+					.getServiceConfiguration();
+			serviceExecutionLog.setClimateService(climateService);
+			serviceExecutionLog.setDataUrl(dataUrl);
+			serviceExecutionLog.setPlotUrl(plotUrl);
+			serviceExecutionLog.setExecutionEndTime(executionEndTime);
+			serviceExecutionLog.setExecutionStartTime(executionStartTime);
+			serviceExecutionLog.setPurpose(purpose);
+			serviceExecutionLog.setUser(user);
+			serviceExecutionLog.setServiceConfiguration(serviceConfiguration);
+			JsonNode parameters = json.findPath("parameters");
+			Iterator<String> iterator = parameters.fieldNames();
+			while (iterator.hasNext()) {
+				String fieldName = iterator.next();
+				String value = parameters.findPath(fieldName).asText();
+				Parameter parameter = parameterRepository
+						.findByNameAndClimateService(fieldName, climateService);
+				ServiceConfigurationItem serviceConfigurationItem = serviceConfigurationItemRepository
+						.findFirstByParameterAndServiceConfiguration(parameter,
+								serviceConfiguration);
+				serviceConfigurationItem.setValue(value);
+				// if NULL?
+				ServiceConfigurationItem savedServiceConfigurationItem = serviceConfigurationItemRepository
+						.save(serviceConfigurationItem);
+				System.out.println("ServiceConfigurationItem saved: "
+						+ savedServiceConfigurationItem.getId());
+			}
+
+			ServiceExecutionLog savedServiceExecutionLog = serviceExecutionLogRepository
+					.save(serviceExecutionLog);
+
+			System.out.println("ServiceExecutionLog updated: "
+					+ savedServiceExecutionLog.getId());
+			return created("ServiceExecutionLog updated: "
+					+ savedServiceExecutionLog.getId());
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("ServiceExecutionLog not updated: " + id);
+			return badRequest("ServiceExecutionLog not updated: " + id);
+		}
+	}
+
+	public Result getServiceExecutionLog(Long id, String format) {
+		if (id < 0) {
+			System.out.println("id is negative!");
+			return badRequest("id is negative!");
+		}
+
+		ServiceExecutionLog serviceExecutionLog = serviceExecutionLogRepository
+				.findOne(id);
+		if (serviceExecutionLog == null) {
+			System.out.println("ServiceExecutionLog not found with id: " + id);
+			return notFound("ServiceExecutionLog not found with id: " + id);
+		}
+
+		String result = new String();
+		if (format.equals("json")) {
+			result = new Gson().toJson(serviceExecutionLog);
+		}
+
+		return ok(result);
+	}
+
+	public Result getAllServiceExecutionLogs(String format) {
+		String result = new String();
+
+		if (format.equals("json")) {
+			result = new Gson().toJson(serviceExecutionLogRepository.findAllByOrderByExecutionStartTimeDesc());
+		}
+
+		return ok(result);
+	}
+
+//	public Result replaceUserWithPurpose() {
+//
+//		//Replace the previous
+//		Iterable<ServiceExecutionLog> executionLogs = serviceExecutionLogRepository.findAll();
+//
+//		HashMap<String, User> uniqueUsers = new HashMap<>();
+//		for (ServiceExecutionLog log : executionLogs) {
+//			String name = log.getUser().getFirstName();
+//			if (name.startsWith("CCS student"))
+//			{
+//				if (!uniqueUsers.containsKey(name))
+//				{
+//					uniqueUsers.put(name,log.getUser());
+//				}
+//				else
+//				{
+//					log.setUser(uniqueUsers.get(name));
+//					serviceExecutionLogRepository.save(log);
+//				}
+//			}
+//		}
+
+
+		// Get all execution logs with userid = 1
+//		List<ServiceExecutionLog> executionLogs = serviceExecutionLogRepository.findByUser_Id(1);
+
+//		if(executionLogs == null || executionLogs.isEmpty()){
+//			System.out.println("No logs need to be updated");
+//			return notFound("No logs need to be updated");
+//		}
+
+		// For each log, set its user to a new user with new name
+//		for(ServiceExecutionLog log: executionLogs){
+//			String userName = "";
+//			String purpose = log.getPurpose().trim();
+//			if(purpose.startsWith("CCS student")) {
+//				System.out.println(purpose);
+//				// Temporarily
+//				userName = purpose.substring(0, 11)+" ";
+//				for(int i = 12; i < purpose.length(); i++)
+//					if(Character.isDigit(purpose.charAt(i))){
+//						userName += purpose.charAt(i);
+//					}
+//					else break;
+//				User newUser = new User(userName,"", "", "", "", "", "", "", "", "", "");
+//				userRepository.save(newUser);
+//				log.setUser(newUser);
+//				serviceExecutionLogRepository.save(log);
+//			}
+//		}
+//
+//		String result = new Gson().toJson(serviceExecutionLogRepository.findAll());
+//
+//		return ok(result);
+//	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/controllers/UserController.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/controllers/UserController.java b/ApacheCMDA-Backend/app/controllers/UserController.java
new file mode 100644
index 0000000..28ec61c
--- /dev/null
+++ b/ApacheCMDA-Backend/app/controllers/UserController.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package controllers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import models.User;
+import models.UserRepository;
+import play.mvc.*;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.persistence.PersistenceException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.Gson;
+
+/**
+ * The main set of web services.
+ */
+@Named
+@Singleton
+public class UserController extends Controller {
+
+	private final UserRepository userRepository;
+
+	// We are using constructor injection to receive a repository to support our
+	// desire for immutability.
+	@Inject
+	public UserController(final UserRepository userRepository) {
+		this.userRepository = userRepository;
+	}
+
+	public Result addUser() {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out.println("User not created, expecting Json data");
+			return badRequest("User not created, expecting Json data");
+		}
+
+		// Parse JSON file
+		String userName = json.path("userName").asText();
+		String password = json.path("password").asText();
+		String firstName = json.path("firstName").asText();
+		String lastName = json.path("lastName").asText();
+		String middleInitial = json.path("middleInitial").asText();
+	    String affiliation = json.path("affiliation").asText();
+	    String title = json.path("title").asText();
+	    String email = json.path("email").asText();
+	    String mailingAddress = json.path("mailingAddress").asText();
+	    String phoneNumber = json.path("phoneNumber").asText();
+	    String faxNumber = json.path("faxNumber").asText();
+	    String researchFields = json.path("researchFields").asText();
+	    String highestDegree = json.path("highestDegree").asText();
+
+		try {
+			if (userRepository.findByUserName(userName).size()>0) {
+				System.out.println("UserName has been used: " + userName);
+				return badRequest("UserName has been used");
+			}
+			User user = new User(userName, password, firstName, lastName, middleInitial, affiliation, title, email, mailingAddress, phoneNumber, faxNumber, researchFields, highestDegree);	
+			userRepository.save(user);
+			System.out.println("User saved: " + user.getId());
+			return created(new Gson().toJson(user.getId()));
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("User not saved: " + firstName + " " + lastName);
+			return badRequest("User not saved: " + firstName + " " + lastName);
+		}
+	}
+
+	public Result deleteUser(Long id) {
+		User deleteUser = userRepository.findOne(id);
+		if (deleteUser == null) {
+			System.out.println("User not found with id: " + id);
+			return notFound("User not found with id: " + id);
+		}
+
+		userRepository.delete(deleteUser);
+		System.out.println("User is deleted: " + id);
+		return ok("User is deleted: " + id);
+	}
+
+	public Result updateUser(long id) {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out.println("User not saved, expecting Json data");
+			return badRequest("User not saved, expecting Json data");
+		}
+
+		// Parse JSON file
+		String firstName = json.path("firstName").asText();
+		String lastName = json.path("lastName").asText();
+		String middleInitial = json.path("middleInitial").asText();
+	    String affiliation = json.path("affiliation").asText();
+	    String title = json.path("title").asText();
+	    String email = json.path("email").asText();
+	    String mailingAddress = json.path("mailingAddress").asText();
+	    String phoneNumber = json.path("phoneNumber").asText();
+	    String faxNumber = json.path("faxNumber").asText();
+	    String researchFields = json.path("researchFields").asText();
+	    String highestDegree = json.path("highestDegree").asText();
+		try {
+			User updateUser = userRepository.findOne(id);
+
+			updateUser.setFirstName(firstName);
+			updateUser.setLastName(lastName);
+			updateUser.setAffiliation(affiliation);
+			updateUser.setEmail(email);
+			updateUser.setFaxNumber(faxNumber);
+			updateUser.setHighestDegree(highestDegree);
+			updateUser.setMailingAddress(mailingAddress);
+			updateUser.setMiddleInitial(middleInitial);
+			updateUser.setPhoneNumber(phoneNumber);
+			updateUser.setResearchFields(researchFields);
+			updateUser.setTitle(title);
+			
+			User savedUser = userRepository.save(updateUser);
+			System.out.println("User updated: " + savedUser.getFirstName()
+					+ " " + savedUser.getLastName());
+			return created("User updated: " + savedUser.getFirstName() + " "
+					+ savedUser.getLastName());
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("User not updated: " + firstName + " "
+					+ lastName);
+			return badRequest("User not updated: " + firstName + " " + lastName);
+		}
+	}
+
+	public Result getUser(Long id, String format) {
+		if (id == null) {
+			System.out.println("User id is null or empty!");
+			return badRequest("User id is null or empty!");
+		}
+
+		User user = userRepository.findOne(id);
+
+		if (user == null) {
+			System.out.println("User not found with with id: " + id);
+			return notFound("User not found with with id: " + id);
+		}
+		String result = new String();
+		if (format.equals("json")) {
+			result = new Gson().toJson(user);
+		}
+
+		return ok(result);
+	}
+	
+	public Result getAllUsers(String format) {
+		Iterable<User> userIterable = userRepository.findAll();
+		List<User> userList = new ArrayList<User>();
+		for (User user : userIterable) {
+			userList.add(user);
+		}
+		String result = new String();
+		if (format.equals("json")) {
+			result = new Gson().toJson(userList);
+		}
+		return ok(result);
+	}
+	
+	public Result isUserValid() {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out.println("Cannot check user, expecting Json data");
+			return badRequest("Cannot check user, expecting Json data");
+		}
+		String email = json.path("email").asText();
+		String password = json.path("password").asText();
+		User user = userRepository.findByEmail(email);
+		if (user.getPassword().equals(password)) {
+			System.out.println("User is valid");
+			return ok("User is valid");
+		} else {
+			System.out.println("User is not valid");
+			return badRequest("User is not valid");
+		}
+	}
+	
+	public Result deleteUserByUserNameandPassword(String userName, String password) {
+		try {
+			List<User> users = userRepository.findByUserName(userName);
+			if (users.size()==0) {
+				System.out.println("User is not existed");
+				return badRequest("User is not existed");
+			}
+			User user = users.get(0);
+			if (user.getPassword().equals(password)) {
+				System.out.println("User is deleted: "+user.getId());
+				userRepository.delete(user);
+				return ok("User is deleted");
+			}
+			else {
+				System.out.println("User is not deleted for wrong password");
+				return badRequest("User is not deleted for wrong password");
+			}
+		}
+		catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("User is not deleted");
+			return badRequest("User is not deleted");
+		}
+		
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/controllers/WorkflowController.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/controllers/WorkflowController.java b/ApacheCMDA-Backend/app/controllers/WorkflowController.java
new file mode 100644
index 0000000..b8fb2ec
--- /dev/null
+++ b/ApacheCMDA-Backend/app/controllers/WorkflowController.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package controllers;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.persistence.PersistenceException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.gson.Gson;
+
+import models.ClimateService;
+import models.ClimateServiceRepository;
+import models.DatasetEntryRepository;
+import models.DatasetLogRepository;
+import models.DatasetRepository;
+import models.Parameter;
+import models.ParameterRepository;
+import models.ServiceConfiguration;
+import models.ServiceConfigurationItem;
+import models.ServiceConfigurationItemRepository;
+import models.ServiceConfigurationRepository;
+import models.ServiceEntryRepository;
+import models.ServiceExecutionLog;
+import models.ServiceExecutionLogRepository;
+import models.User;
+import models.UserRepository;
+import models.Workflow;
+import models.WorkflowRepository;
+import play.mvc.*;
+import workflow.VisTrailJson;
+
+@Named
+@Singleton
+public class WorkflowController extends Controller {
+	public static final String WILDCARD = "%";
+
+	private final ClimateServiceRepository climateServiceRepository;
+	private final UserRepository userRepository;
+	private final WorkflowRepository workflowRepository;
+	private final ParameterRepository parameterRepository;
+	private final ServiceExecutionLogRepository serviceExecutionLogRepository;
+	private final ServiceConfigurationItemRepository serviceConfigurationItemRepository;
+	private final DatasetLogRepository datasetLogRepository;
+	private final ServiceConfigurationRepository serviceConfigurationRepository;
+	private final ServiceEntryRepository serviceEntryRepository;
+	private final DatasetEntryRepository datasetEntryRepository;
+	private final DatasetRepository datasetRepository;
+
+	@Inject
+	public WorkflowController(
+			ClimateServiceRepository climateServiceRepository,
+			UserRepository userRepository,
+			WorkflowRepository workflowRepository,
+			ParameterRepository parameterRepository,
+			ServiceExecutionLogRepository serviceExecutionLogRepository,
+			ServiceConfigurationItemRepository serviceConfigurationItemRepository,
+			DatasetLogRepository datasetLogRepository,
+			ServiceConfigurationRepository serviceConfigurationRepository,
+			ServiceEntryRepository serviceEntryRepository,
+			DatasetEntryRepository datasetEntryRepository,
+			DatasetRepository datasetRepository) {
+		this.climateServiceRepository = climateServiceRepository;
+		this.userRepository = userRepository;
+		this.workflowRepository = workflowRepository;
+		this.parameterRepository = parameterRepository;
+		this.serviceExecutionLogRepository = serviceExecutionLogRepository;
+		this.serviceConfigurationItemRepository = serviceConfigurationItemRepository;
+		this.datasetLogRepository = datasetLogRepository;
+		this.serviceConfigurationRepository = serviceConfigurationRepository;
+		this.serviceEntryRepository = serviceEntryRepository;
+		this.datasetEntryRepository = datasetEntryRepository;
+		this.datasetRepository = datasetRepository;
+	}
+
+	public Result addWorkflow() {
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out.println("Dataset not saved, expecting Json data");
+			return badRequest("Dataset not saved, expecting Json data");
+		}
+		String name = json.findPath("name").asText();
+		String purpose = json.findPath("purpose").asText();
+		long createTimeNumber = json.findPath("createTime").asLong();
+		Date createTime = new Date(createTimeNumber);
+		String versionNo = json.findPath("versionNo").asText();
+		long rootWorkflowId = json.findPath("rootWorkflowId").asLong();
+
+		JsonNode users = json.findPath("userId");
+		List<User> userSet = new ArrayList<User>();
+		for (int i = 0; i < users.size(); i++) {
+			userSet.add(userRepository.findOne(users.get(i).asLong()));
+		}
+		JsonNode climateServices = json.findPath("climateServiceId");
+		List<ClimateService> climateServiceSet = new ArrayList<ClimateService>();
+		for (int i = 0; i < climateServices.size(); i++) {
+			climateServiceSet.add(climateServiceRepository
+					.findOne(climateServices.get(i).asLong()));
+		}
+		try {
+			Workflow workflow = new Workflow(name, purpose, createTime,
+					versionNo, rootWorkflowId, userSet, climateServiceSet);
+			Workflow savedWorkflow = workflowRepository.save(workflow);
+			System.out.println("Workflow saved: " + savedWorkflow.getId());
+			return created(new Gson().toJson("Workflow saved: "
+					+ savedWorkflow.getId()));
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("Workflow not created");
+			return badRequest("Workflow not created");
+		}
+
+	}
+
+	public Result updateWorkflowById(long id) {
+		if (id < 0) {
+			System.out.println("id is negative!");
+			return badRequest("id is negative!");
+		}
+		JsonNode json = request().body().asJson();
+		if (json == null) {
+			System.out.println("Workflow not saved, expecting Json data");
+			return badRequest("Workflow not saved, expecting Json data");
+		}
+		String name = json.findPath("name").asText();
+		String purpose = json.findPath("purpose").asText();
+		long createTimeNumber = json.findPath("createTime").asLong();
+		Date createTime = new Date(createTimeNumber);
+		String versionNo = json.findPath("versionNo").asText();
+		long rootWorkflowId = json.findPath("rootWorkflowId").asLong();
+
+		JsonNode users = json.findPath("userId");
+		List<User> userSet = new ArrayList<User>();
+		for (int i = 0; i < users.size(); i++) {
+			userSet.add(userRepository.findOne(users.get(i).asLong()));
+		}
+		JsonNode climateServices = json.findPath("climateServiceId");
+		List<ClimateService> climateServiceSet = new ArrayList<ClimateService>();
+		for (int i = 0; i < climateServices.size(); i++) {
+			climateServiceSet.add(climateServiceRepository
+					.findOne(climateServices.get(i).asLong()));
+		}
+
+		try {
+			Workflow workflow = workflowRepository.findOne(id);
+
+			workflow.setClimateServiceSet(climateServiceSet);
+			workflow.setCreateTime(createTime);
+			workflow.setName(name);
+			workflow.setPurpose(purpose);
+			workflow.setRootWorkflowId(rootWorkflowId);
+			workflow.setUserSet(userSet);
+			workflow.setVersionNo(versionNo);
+
+			Workflow savedWorkflow = workflowRepository.save(workflow);
+
+			System.out.println("Workflow updated: " + savedWorkflow.getId());
+			return created("Workflow updated: " + savedWorkflow.getId());
+		} catch (PersistenceException pe) {
+			pe.printStackTrace();
+			System.out.println("Workflow not saved: " + id);
+			return badRequest("Workflow not saved: " + id);
+		}
+	}
+
+	public Result deleteWorkflowById(long id) {
+		if (id < 0) {
+			System.out.println("id is negative!");
+			return badRequest("id is negative!");
+		}
+		Workflow workflow = workflowRepository.findOne(id);
+		if (workflow == null) {
+			System.out.println("Workflow not found with id: " + id);
+			return notFound("Workflow not found with id: " + id);
+		}
+		workflowRepository.delete(workflow);
+		System.out.println("Workflow is deleted: " + id);
+		return ok("Workflow is deleted: " + id);
+	}
+
+	public Result getWorkflowById(long id, String format) {
+		if (id < 0) {
+			System.out.println("id is negative!");
+			return badRequest("id is negative!");
+		}
+		Workflow workflow = workflowRepository.findOne(id);
+		if (workflow == null) {
+			System.out.println("Workflow not found with name: " + id);
+			return notFound("Workflow not found with name: " + id);
+		}
+
+		String result = new String();
+		if (format.equals("json")) {
+			result = new Gson().toJson(workflow);
+		}
+
+		return ok(result);
+	}
+
+	public Result getAllWorkflows(String format) {
+		try {
+			Iterable<Workflow> workflows = workflowRepository.findAll();
+			String result = new String();
+			result = new Gson().toJson(workflows);
+			return ok(result);
+		} catch (Exception e) {
+			return badRequest("Workflows not found");
+		}
+	}
+
+	public Result generateWorkflowJson() {
+		ServiceExecutionLogController serviceExecutionLogController = new ServiceExecutionLogController(
+				serviceExecutionLogRepository, parameterRepository,
+				serviceConfigurationItemRepository, userRepository,
+				climateServiceRepository, datasetLogRepository,
+				serviceConfigurationRepository, serviceEntryRepository,
+				datasetEntryRepository, datasetRepository);
+		List<ServiceExecutionLog> list = serviceExecutionLogController
+				.queryServiceExecutionLogsAsList();
+		String result = VisTrailJson.getVisTrailJson(list);
+		String timeStamp = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss")
+				.format(new Date());
+		String location = "workflowRepository/" + timeStamp + ".json";
+
+		File theDir = new File("workflowRepository");
+
+		// if the directory does not exist, create it
+		if (!theDir.exists()) {
+			System.out.println("creating directory: " + workflowRepository);
+			boolean create = false;
+
+			try {
+				theDir.mkdir();
+				create = true;
+			} catch (SecurityException se) {
+				// handle it
+			}
+			if (create) {
+				System.out.println("DIR created");
+			}
+		} else {
+			System.out.println("No");
+		}
+
+		try {
+			File file = new File(location);
+			BufferedWriter output = new BufferedWriter(new FileWriter(file));
+			output.write(result);
+			output.close();
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		return ok(result);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/.DS_Store
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/.DS_Store b/ApacheCMDA-Backend/app/models/.DS_Store
new file mode 100644
index 0000000..a0536ab
Binary files /dev/null and b/ApacheCMDA-Backend/app/models/.DS_Store differ

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BookChapterPublication.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BookChapterPublication.java b/ApacheCMDA-Backend/app/models/BookChapterPublication.java
new file mode 100644
index 0000000..91f7e55
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BookChapterPublication.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import javax.persistence.Entity;
+import javax.persistence.PrimaryKeyJoinColumn;
+
+@Entity
+@PrimaryKeyJoinColumn(name = "bookChapterPublicationId", referencedColumnName = "id")//referencedColumnName
+public class BookChapterPublication extends Publication {
+
+	private String bookName;
+	private String editorName;
+	private String time;
+	
+	public BookChapterPublication() {
+		super();
+	}	
+
+	public BookChapterPublication(String paperTitle, User author,
+			String publicationChannel, int year, String bookName,
+			String editorName, String time) {
+		super(paperTitle, author, publicationChannel, year);
+		this.bookName = bookName;
+		this.editorName = editorName;
+		this.time = time;
+	}
+
+
+
+	public String getBookName() {
+		return bookName;
+	}
+	public void setBookName(String bookName) {
+		this.bookName = bookName;
+	}
+	public String getEditorName() {
+		return editorName;
+	}
+	public void setEditorName(String editorName) {
+		this.editorName = editorName;
+	}
+	public String getTime() {
+		return time;
+	}
+	public void setTime(String time) {
+		this.time = time;
+	}
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BookChapterPublicationRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BookChapterPublicationRepository.java b/ApacheCMDA-Backend/app/models/BookChapterPublicationRepository.java
new file mode 100644
index 0000000..0c8e736
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BookChapterPublicationRepository.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface BookChapterPublicationRepository extends CrudRepository<BookChapterPublication, Long> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BookPublication.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BookPublication.java b/ApacheCMDA-Backend/app/models/BookPublication.java
new file mode 100644
index 0000000..90d068b
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BookPublication.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import javax.persistence.Entity;
+import javax.persistence.PrimaryKeyJoinColumn;
+
+@Entity
+@PrimaryKeyJoinColumn(name = "bookPublicationId", referencedColumnName = "id")//referencedColumnName
+public class BookPublication extends Publication {
+	private String bookName;
+	//private String publisherName;
+	private String publisherLocation;
+	private String time;
+	private String pages;
+	
+	public BookPublication() {
+	}
+
+	public BookPublication(String paperTitle, User author,
+			String publicationChannel, int year, String bookName, String publisherLocation,
+			String time, String pages) {
+		super(paperTitle, author, publicationChannel, year);
+		this.bookName = bookName;
+		this.publisherLocation = publisherLocation;
+		this.time = time;
+		this.pages = pages;
+	}
+
+	public String getBookName() {
+		return bookName;
+	}
+
+	public void setBookName(String bookName) {
+		this.bookName = bookName;
+	}
+
+	public String getPublisherLocation() {
+		return publisherLocation;
+	}
+
+	public void setPublisherLocation(String publisherLocation) {
+		this.publisherLocation = publisherLocation;
+	}
+
+	public String getTime() {
+		return time;
+	}
+
+	public void setTime(String time) {
+		this.time = time;
+	}
+
+	public String getPages() {
+		return pages;
+	}
+
+	public void setPages(String pages) {
+		this.pages = pages;
+	}
+
+	@Override
+	public String toString() {
+		return "BookPublication [bookName=" + bookName + ", publisherLocation="
+				+ publisherLocation + ", time=" + time + ", pages=" + pages
+				+ ", toString()=" + super.toString() + "]";
+	}
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BookPublicationRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BookPublicationRepository.java b/ApacheCMDA-Backend/app/models/BookPublicationRepository.java
new file mode 100644
index 0000000..ec3cba3
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BookPublicationRepository.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface BookPublicationRepository extends CrudRepository<BookPublication, Long> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BugReport.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BugReport.java b/ApacheCMDA-Backend/app/models/BugReport.java
new file mode 100644
index 0000000..b18f89c
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BugReport.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+
+
+import java.util.Date;
+
+/**
+ * Created by raoli on 4/1/15.
+ */
+@Entity
+public class BugReport {
+
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	private long id;
+
+	private String title;
+	private String email;
+	private String name;
+	private String organization;
+	private String description;
+	private int solved = 0;
+	private Date creationDate;
+	private Date updateDate;
+
+	public BugReport() {
+
+	}
+
+	public BugReport(String title, String email, String name,
+					 String organization, String description, int solved,
+					 Date creationDate, Date updateDate) {
+		super();
+		this.title = title;
+		this.email = email;
+		this.name = name;
+		this.organization = organization;
+		this.description = description;
+		this.solved = solved;
+		this.creationDate = creationDate;
+		this.updateDate = updateDate;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public String toString() {
+		return "BugReport #" + id;
+	}
+
+	public String getTitle() {
+		return this.title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public String getDescription() {
+		return this.description;
+	}
+
+	public String getEmail() {
+		return email;
+	}
+
+	public void setEmail(String email) {
+		this.email = email;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getOrganization() {
+		return organization;
+	}
+
+	public void setOrganization(String organization) {
+		this.organization = organization;
+	}
+
+	public void setDescription(String description) {
+		this.description = description;
+	}
+
+	public int getSolved() {
+		return solved;
+	}
+
+	public void setSolved(int solved) {
+		this.solved = solved;
+	}
+
+
+	public Date getCreationDate() {
+		return creationDate;
+	}
+
+	public void setCreationDate(Date creationDate) {
+		this.creationDate = creationDate;
+	}
+
+	public Date getUpdateDate() {
+		return updateDate;
+	}
+
+	public void setUpdateDate(Date updateDate) {
+		this.updateDate = updateDate;
+	}
+	
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/BugReportRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/BugReportRepository.java b/ApacheCMDA-Backend/app/models/BugReportRepository.java
new file mode 100644
index 0000000..3faf4d9
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/BugReportRepository.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.List;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface BugReportRepository extends CrudRepository<BugReport, Long> {
+	List<BugReport> findAllBySolved(int solved);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/ClimateService.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/ClimateService.java b/ApacheCMDA-Backend/app/models/ClimateService.java
new file mode 100644
index 0000000..9f6530b
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/ClimateService.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.Date;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+@Entity
+public class ClimateService {
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	private long id;
+	private long rootServiceId;
+	@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
+	@JoinColumn(name = "creatorId", referencedColumnName = "id")
+	private User user;
+	private String name;
+	private String purpose;
+	private String url;
+	private String scenario;
+	@Temporal(TemporalType.TIMESTAMP)
+	private Date createTime;
+
+	private String versionNo;
+
+	public ClimateService() {
+	}
+
+	public ClimateService(long rootServiceId, User user, String name,
+			String purpose, String url, String scenario, Date createTime,
+			String versionNo) {
+		super();
+		this.rootServiceId = rootServiceId;
+		this.user = user;
+		this.name = name;
+		this.purpose = purpose;
+		this.url = url;
+		this.scenario = scenario;
+		// For creation time, can just use current time like this
+		if (createTime == null)
+			createTime = new Date();
+		this.createTime = createTime;
+		this.versionNo = versionNo;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public long getRootServiceId() {
+		return rootServiceId;
+	}
+
+	public void setRootServiceId(long rootServiceId) {
+		this.rootServiceId = rootServiceId;
+	}
+
+	public User getUser() {
+		return user;
+	}
+	
+	public void setUser(User user) {
+		this.user = user;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getPurpose() {
+		return purpose;
+	}
+
+	public void setPurpose(String purpose) {
+		this.purpose = purpose;
+	}
+
+	public String getUrl() {
+		return url;
+	}
+
+	public void setUrl(String url) {
+		this.url = url;
+	}
+
+	public String getScenario() {
+		return scenario;
+	}
+
+	public void setScenario(String scenario) {
+		this.scenario = scenario;
+	}
+
+	public Date getCreateTime() {
+		return createTime;
+	}
+
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+
+	public String getVersionNo() {
+		return versionNo;
+	}
+
+	public void setVersionNo(String versionNo) {
+		this.versionNo = versionNo;
+	}
+
+	@Override
+	public String toString() {
+		return "ClimateService [id=" + id + ", rootServiceId=" + rootServiceId
+				+ ", user=" + user + ", name=" + name + ", purpose=" + purpose
+				+ ", url=" + url + ", scenario=" + scenario + ", createTime="
+				+ createTime + ", versionNo=" + versionNo + "]";
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/ClimateServiceRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/ClimateServiceRepository.java b/ApacheCMDA-Backend/app/models/ClimateServiceRepository.java
new file mode 100644
index 0000000..1063d47
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/ClimateServiceRepository.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface ClimateServiceRepository extends CrudRepository<ClimateService, Long> {
+	List<ClimateService> findAllByName(String name);
+	ClimateService findFirstByName(String oldName);
+    List<ClimateService> findByOrderByCreateTimeDesc();
+	// select c.*, sum(s.count) as totalcount from ClimateService c, ServiceEntry s where c.id=s.serviceId group by s.serviceId order by totalcount desc;
+	@Query(value = "select c.* from ClimateService c, ServiceEntry s where c.id=s.serviceId group by s.serviceId order by sum(s.count) desc", nativeQuery = true)
+	List<ClimateService> getClimateServiceOrderByCount();
+
+	@Query(value = "select c.* from ClimateService c, ServiceEntry s where c.id=s.serviceId group by s.serviceId order by s.latestAccessTimeStamp desc", nativeQuery = true)
+	List<ClimateService> getClimateServiceOrderByLatestAccessTime();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/ConferencePublication.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/ConferencePublication.java b/ApacheCMDA-Backend/app/models/ConferencePublication.java
new file mode 100644
index 0000000..96b3d6d
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/ConferencePublication.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+
+import javax.persistence.Entity;
+import javax.persistence.PrimaryKeyJoinColumn;
+
+@Entity
+@PrimaryKeyJoinColumn(name = "conferencePublicationId", referencedColumnName = "id")
+public class ConferencePublication extends Publication {
+
+	private String name;
+	private String location;
+	private String time;
+	private String page;
+	
+	
+	public ConferencePublication() {
+		super();
+	}	
+	
+	public ConferencePublication(String paperTitle, User author,
+			String publicationChannel, int year, String name, String location,
+			String time, String page) {
+		super(paperTitle, author, publicationChannel, year);
+		this.name = name;
+		this.location = location;
+		this.time = time;
+		this.page = page;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public String getLocation() {
+		return location;
+	}
+	public void setLocation(String location) {
+		this.location = location;
+	}
+	public String getTime() {
+		return time;
+	}
+	public void setTime(String time) {
+		this.time = time;
+	}
+	public String getPage() {
+		return page;
+	}
+	public void setPage(String page) {
+		this.page = page;
+	}
+	
+	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/ConferencePublicationRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/ConferencePublicationRepository.java b/ApacheCMDA-Backend/app/models/ConferencePublicationRepository.java
new file mode 100644
index 0000000..c0daced
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/ConferencePublicationRepository.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import org.springframework.data.repository.CrudRepository;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+@Named
+@Singleton
+public interface ConferencePublicationRepository extends CrudRepository<ConferencePublication, Long> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/Dataset.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/Dataset.java b/ApacheCMDA-Backend/app/models/Dataset.java
new file mode 100644
index 0000000..1f0e21d
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/Dataset.java
@@ -0,0 +1,289 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+
+
+@Entity
+public class Dataset {
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.AUTO)
+	private long id;
+	private String name;
+	private String dataSourceNameinWebInterface;
+	private String agencyId;
+	@ManyToOne(optional = false)
+	@JoinColumn(name = "instrumentId", referencedColumnName = "id")
+	private Instrument instrument;
+	@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE})
+	@JoinTable(name = "DatasetAndService", joinColumns = { @JoinColumn(name ="datasetId", referencedColumnName = "id")}, inverseJoinColumns = { @JoinColumn(name = "climateServiceId", referencedColumnName = "id") })
+	private List<ClimateService> climateServiceSet;
+	private Date publishTimeStamp;
+	private String url;
+	private String physicalVariable;
+	private String CMIP5VarName;
+	private String units;
+	private String gridDimension;
+	private String source;
+	private String status;
+	private String responsiblePerson;
+	private String variableNameInWebInterface;
+	private String dataSourceInputParameterToCallScienceApplicationCode;
+	private String variableNameInputParameterToCallScienceApplicationCode;
+	private String comment;
+	private Date startTime;
+	private Date endTime;
+	
+
+	public Dataset() {
+	}
+	
+	public Dataset(String name, String dataSourceNameinWebInterface,
+			String agencyId, Instrument instrument,
+			List<ClimateService> climateServiceSet, Date publishTimeStamp,
+			String url, String physicalVariable, String cMIP5VarName,
+			String units, String gridDimension, String source, String status,
+			String responsiblePerson, String variableNameInWebInterface,
+			String dataSourceInputParameterToCallScienceApplicationCode,
+			String variableNameInputParameterToCallScienceApplicationCode,
+			String comment, Date startTime, Date endTime) {
+		super();
+		this.name = name;
+		this.dataSourceNameinWebInterface = dataSourceNameinWebInterface;
+		this.agencyId = agencyId;
+		this.instrument = instrument;
+		this.climateServiceSet = climateServiceSet;
+		this.publishTimeStamp = publishTimeStamp;
+		this.url = url;
+		this.physicalVariable = physicalVariable;
+		CMIP5VarName = cMIP5VarName;
+		this.units = units;
+		this.gridDimension = gridDimension;
+		this.source = source;
+		this.status = status;
+		this.responsiblePerson = responsiblePerson;
+		this.variableNameInWebInterface = variableNameInWebInterface;
+		this.dataSourceInputParameterToCallScienceApplicationCode = dataSourceInputParameterToCallScienceApplicationCode;
+		this.variableNameInputParameterToCallScienceApplicationCode = variableNameInputParameterToCallScienceApplicationCode;
+		this.comment = comment;
+		this.startTime = startTime;
+		this.endTime = endTime;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getDataSourceNameinWebInterface() {
+		return dataSourceNameinWebInterface;
+	}
+
+	public String getAgencyId() {
+		return agencyId;
+	}
+
+	public Instrument getInstrument() {
+		return instrument;
+	}
+
+	public List<ClimateService> getClimateServiceSet() {
+		return climateServiceSet;
+	}
+
+	public Date getPublishTimeStamp() {
+		return publishTimeStamp;
+	}
+
+	public String getUrl() {
+		return url;
+	}
+
+	public String getPhysicalVariable() {
+		return physicalVariable;
+	}
+
+	public String getCMIP5VarName() {
+		return CMIP5VarName;
+	}
+
+	public String getUnits() {
+		return units;
+	}
+
+	public String getGridDimension() {
+		return gridDimension;
+	}
+
+	public String getSource() {
+		return source;
+	}
+
+	public String getStatus() {
+		return status;
+	}
+
+	public String getResponsiblePerson() {
+		return responsiblePerson;
+	}
+
+	public String getVariableNameInWebInterface() {
+		return variableNameInWebInterface;
+	}
+
+	public String getDataSourceInputParameterToCallScienceApplicationCode() {
+		return dataSourceInputParameterToCallScienceApplicationCode;
+	}
+
+	public String getVariableNameInputParameterToCallScienceApplicationCode() {
+		return variableNameInputParameterToCallScienceApplicationCode;
+	}
+
+	public String getComment() {
+		return comment;
+	}
+	
+	public Date getStartTime() {
+		return startTime;
+	}
+	
+	public Date getEndTime() {
+		return endTime;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setDataSourceNameinWebInterface(String dataSourceNameinWebInterface) {
+		this.dataSourceNameinWebInterface = dataSourceNameinWebInterface;
+	}
+
+	public void setAgencyId(String agencyId) {
+		this.agencyId = agencyId;
+	}
+
+	public void setInstrument(Instrument instrument) {
+		this.instrument = instrument;
+	}
+
+	public void setClimateServiceSet(List<ClimateService> climateServiceSet) {
+		this.climateServiceSet = climateServiceSet;
+	}
+
+	public void setPublishTimeStamp(Date publishTimeStamp) {
+		this.publishTimeStamp = publishTimeStamp;
+	}
+
+	public void setUrl(String url) {
+		this.url = url;
+	}
+
+	public void setPhysicalVariable(String physicalVariable) {
+		this.physicalVariable = physicalVariable;
+	}
+
+	public void setCMIP5VarName(String cMIP5VarName) {
+		CMIP5VarName = cMIP5VarName;
+	}
+
+	public void setUnits(String units) {
+		this.units = units;
+	}
+
+	public void setGridDimension(String gridDimension) {
+		this.gridDimension = gridDimension;
+	}
+
+	public void setSource(String source) {
+		this.source = source;
+	}
+
+	public void setStatus(String status) {
+		this.status = status;
+	}
+
+	public void setResponsiblePerson(String responsiblePerson) {
+		this.responsiblePerson = responsiblePerson;
+	}
+
+	public void setVariableNameInWebInterface(String variableNameInWebInterface) {
+		this.variableNameInWebInterface = variableNameInWebInterface;
+	}
+
+	public void setDataSourceInputParameterToCallScienceApplicationCode(
+			String dataSourceInputParameterToCallScienceApplicationCode) {
+		this.dataSourceInputParameterToCallScienceApplicationCode = dataSourceInputParameterToCallScienceApplicationCode;
+	}
+
+	public void setVariableNameInputParameterToCallScienceApplicationCode(
+			String variableNameInputParameterToCallScienceApplicationCode) {
+		this.variableNameInputParameterToCallScienceApplicationCode = variableNameInputParameterToCallScienceApplicationCode;
+	}
+
+	public void setComment(String comment) {
+		this.comment = comment;
+	}
+
+	public void setStartTime(Date startTime) {
+		this.startTime = startTime;
+	}
+
+	public void setEndTime(Date endTime) {
+		this.endTime = endTime;
+	}
+
+	@Override
+	public String toString() {
+		return "Dataset [id=" + id + ", name=" + name
+				+ ", dataSourceNameinWebInterface="
+				+ dataSourceNameinWebInterface + ", agencyId=" + agencyId
+				+ ", instrument=" + instrument + ", climateServiceSet="
+				+ climateServiceSet + ", publishTimeStamp=" + publishTimeStamp
+				+ ", url=" + url + ", physicalVariable=" + physicalVariable
+				+ ", CMIP5VarName=" + CMIP5VarName + ", units=" + units
+				+ ", gridDimension=" + gridDimension + ", source=" + source
+				+ ", status=" + status + ", responsiblePerson="
+				+ responsiblePerson + ", variableNameInWebInterface="
+				+ variableNameInWebInterface
+				+ ", dataSourceInputParameterToCallScienceApplicationCode="
+				+ dataSourceInputParameterToCallScienceApplicationCode
+				+ ", variableNameInputParameterToCallScienceApplicationCode="
+				+ variableNameInputParameterToCallScienceApplicationCode
+				+ ", comment=" + comment 
+				+ ", startTime=" + startTime + ", endTime=" + endTime
+				+"]";
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/DatasetEntry.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/DatasetEntry.java b/ApacheCMDA-Backend/app/models/DatasetEntry.java
new file mode 100644
index 0000000..d8b34f2
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/DatasetEntry.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import javax.persistence.*;
+
+import java.util.Date;
+
+
+@Entity
+public class DatasetEntry {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    private long id;
+    private String versionNo;
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date registerTimeStamp;
+    private String registerNote;
+    private int count;
+    @Temporal(TemporalType.TIMESTAMP)
+    private Date latestAccessTimeStamp;
+    @ManyToOne(optional = false)
+	@JoinColumn(name = "datasetId", referencedColumnName = "id")
+    Dataset dataset;
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "registorId", referencedColumnName = "id")
+    private User user;
+
+    public DatasetEntry(){
+    }
+
+	public DatasetEntry(String versionNo, Date registerTimeStamp,
+			String registerNote, int count, Date latestAccessTimeStamp,
+			Dataset dataset, User user) {
+		super();
+		this.versionNo = versionNo;
+		this.registerTimeStamp = registerTimeStamp;
+		this.registerNote = registerNote;
+		this.count = count;
+		this.latestAccessTimeStamp = latestAccessTimeStamp;
+		this.dataset = dataset;
+		this.user = user;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public String getVersionNo() {
+		return versionNo;
+	}
+
+	public Date getRegisterTimeStamp() {
+		return registerTimeStamp;
+	}
+
+	public String getRegisterNote() {
+		return registerNote;
+	}
+
+	public int getCount() {
+		return count;
+	}
+
+	public Date getLatestAccessTimeStamp() {
+		return latestAccessTimeStamp;
+	}
+
+	public Dataset getDataset() {
+		return dataset;
+	}
+
+	public User getUser() {
+		return user;
+	}
+	
+	public void setVersionNo(String versionNo) {
+		this.versionNo = versionNo;
+	}
+
+	public void setRegisterTimeStamp(Date registerTimeStamp) {
+		this.registerTimeStamp = registerTimeStamp;
+	}
+
+	public void setRegisterNote(String registerNote) {
+		this.registerNote = registerNote;
+	}
+
+	public void setCount(int count) {
+		this.count = count;
+	}
+
+	public void setLatestAccessTimeStamp(Date latestAccessTimeStamp) {
+		this.latestAccessTimeStamp = latestAccessTimeStamp;
+	}
+
+	public void setDataset(Dataset dataset) {
+		this.dataset = dataset;
+	}
+
+	public void setUser(User user) {
+		this.user = user;
+	}
+
+	@Override
+	public String toString() {
+		return "DatasetEntry [id=" + id + ", versionNo=" + versionNo
+				+ ", registerTimeStamp=" + registerTimeStamp
+				+ ", registerNote=" + registerNote + ", count=" + count
+				+ ", latestAccessTimeStamp=" + latestAccessTimeStamp
+				+ ", dataset=" + dataset + ", user=" + user + "]";
+	}
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cmda/blob/37774c92/ApacheCMDA-Backend/app/models/DatasetEntryRepository.java
----------------------------------------------------------------------
diff --git a/ApacheCMDA-Backend/app/models/DatasetEntryRepository.java b/ApacheCMDA-Backend/app/models/DatasetEntryRepository.java
new file mode 100644
index 0000000..b63d606
--- /dev/null
+++ b/ApacheCMDA-Backend/app/models/DatasetEntryRepository.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package models;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.springframework.data.repository.CrudRepository;
+
+
+
+@Named
+@Singleton
+public interface DatasetEntryRepository extends CrudRepository<DatasetEntry, Long> {
+	List<DatasetEntry> findByDataset(Dataset dataset);
+}
\ No newline at end of file