package com.aemreunal.controller.project; /* * *********************** * * Copyright (c) 2015 * * * * This code belongs to: * * * * @author Ahmet Emre Ünal * * S001974 * * * * aemreunal@gmail.com * * emre.unal@ozu.edu.tr * * * * aemreunal.com * * *********************** * */ import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import java.util.List; import javax.validation.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.util.UriComponentsBuilder; import com.aemreunal.config.GlobalSettings; import com.aemreunal.controller.region.RegionController; import com.aemreunal.controller.user.UserController; import com.aemreunal.domain.Project; import com.aemreunal.service.ProjectService; import static org.springframework.hateoas.core.DummyInvocationUtils.methodOn; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; @Controller @RequestMapping(GlobalSettings.PROJECT_PATH_MAPPING) public class ProjectController { @Autowired private ProjectService projectService; /** * Get all projects of the user. Optionally the user may search their projects by * name * * @param username * The username of the owner of the projects * @param projectName * (Optional) The name of the project * * @return All existing projects (Optionally, all that match the given criteria) */ @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<List<Project>> getAllProjectsOfUser(@PathVariable String username, @RequestParam(value = "name", required = false, defaultValue = "") String projectName) { if (projectName.equals("")) { return new ResponseEntity<List<Project>>(projectService.getAllProjectsOf(username), HttpStatus.OK); } else { return getProjectsWithMatchingCriteria(username, projectName); } } /** * Returns the list of projects that match a given criteria * * @param username * The username of the owner of the projects * @param projectName * (Optional) The name of the project * * @return The list of projects that match the given criteria */ private ResponseEntity<List<Project>> getProjectsWithMatchingCriteria(String username, String projectName) { List<Project> projects = projectService.findProjectsBySpecs(username, projectName); return new ResponseEntity<List<Project>>(projects, HttpStatus.OK); } /** * Get the project with the specified ID * * @param projectId * The ID of the project * * @return The project */ @RequestMapping(method = RequestMethod.GET, value = GlobalSettings.PROJECT_ID_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Project> getProjectById(@PathVariable String username, @PathVariable Long projectId) { Project project = projectService.getProject(username, projectId); return new ResponseEntity<Project>(addLinks(project), HttpStatus.OK); } @RequestMapping(method = RequestMethod.GET, value = GlobalSettings.PROJECT_CONNECTIONS_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<JSONArray> getAllConnectionsOfProject(@PathVariable String username, @PathVariable Long projectId) { JSONArray connections = projectService.getConnectionsOfProject(username, projectId); return new ResponseEntity<JSONArray>(connections, HttpStatus.OK); } /** * Creates a new project from the submitted JSON object in the request body. * <p> * In the case of a constraint violation occurring during the save operation, a {@link * ConstraintViolationException} will be thrown from the {@link * com.aemreunal.service.ProjectService#save(String, com.aemreunal.domain.Project) * save()} method of {@link com.aemreunal.service.ProjectService}, propagated to this * method and then thrown from this one. This exception will be caught by the {@link * com.aemreunal.controller.GeneralControllerAdvice#constraintViolationExceptionHandler(javax.validation.ConstraintViolationException) * constraintViolationExceptionHandler()} of the {@link com.aemreunal.controller.GeneralControllerAdvice * GeneralControllerAdvice} class. * * @param username * The username of the owner of the project * @param projectFromJson * The project as JSON object * @param builder * The URI builder for post-creation redirect * * @return The created project */ @RequestMapping(method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<JSONObject> createProject(@PathVariable String username, @RequestBody Project projectFromJson, UriComponentsBuilder builder) { Project savedProject = projectService.save(username, projectFromJson); GlobalSettings.log("Saved project with Name = \'" + savedProject.getName() + "\' ID = \'" + savedProject.getProjectId() + "\'"); String projectSecret = projectService.resetSecret(username, savedProject); return buildCreateResponse(builder, addLinks(savedProject), projectSecret); } /** * Builds the post-create response for a project. Sets the appropriate headers and * creates a {@link org.springframework.http.ResponseEntity ResponseEntity} object * with {@link net.minidev.json.JSONObject JSONObject} type. * * @param builder * The URI builder for post-creation redirect * @param savedProject * The project to create the response for * @param projectSecret * The secret of the project * * @return The {@link org.springframework.http.ResponseEntity ResponseEntity} for this * project */ private ResponseEntity<JSONObject> buildCreateResponse(UriComponentsBuilder builder, Project savedProject, String projectSecret) { HttpHeaders headers = new HttpHeaders(); headers.setLocation(builder.path(GlobalSettings.PROJECT_SPECIFIC_MAPPING) .buildAndExpand( savedProject.getOwner().getUsername(), savedProject.getProjectId().toString()) .toUri()); return new ResponseEntity<JSONObject>(savedProject.getCreateResponse(projectSecret), headers, HttpStatus.CREATED); } /** * Adds the HATEOAS links to the {@link com.aemreunal.domain.Project Project} object. * * @param project * Project to add the links to * * @return The project with links added * * @see <a href="https://github.com/spring-projects/spring-hateoas#link-builder">Spring * HATEOAS GitHub repo</a> */ private Project addLinks(Project project) { String username = project.getOwner().getUsername(); Long projectId = project.getProjectId(); project.getLinks().add(linkTo(methodOn(ProjectController.class).getProjectById(username, projectId)).withSelfRel()); project.getLinks().add(linkTo(methodOn(RegionController.class).getRegionsOfProject(username, projectId, "")).withRel("regions")); project.getLinks().add(linkTo(methodOn(UserController.class).getUserByUsername(username)).withRel("owner")); return project; } /** * Delete the specified project, along with all the beacons, regions and scenarios in * the project. * <p> * To delete the project, confirmation must be supplied as a URI parameter, in the * form of "?confirm=yes". If not supplied, the project will not be deleted. * * @param username * The username of the owner of the project to delete * @param projectId * The ID of the project to delete * @param confirmation * The confirmation parameter * * @return The deleted project */ @RequestMapping(method = RequestMethod.DELETE, value = GlobalSettings.PROJECT_ID_MAPPING) public ResponseEntity<Project> deleteProject(@PathVariable String username, @PathVariable Long projectId, @RequestParam(value = "confirm", required = true) String confirmation) { if (confirmation.toLowerCase().equals("yes")) { Project deletedProject = projectService.delete(username, projectId); return new ResponseEntity<Project>(deletedProject, HttpStatus.OK); } else { return new ResponseEntity<Project>(HttpStatus.PRECONDITION_FAILED); } } }