package com.ufund.api.ufundapi.controller; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.ufund.api.ufundapi.DuplicateKeyException; import com.ufund.api.ufundapi.model.Need; import com.ufund.api.ufundapi.model.Need.GoalType; import com.ufund.api.ufundapi.service.AuthService; import com.ufund.api.ufundapi.service.CupboardService; @RestController @RequestMapping("cupboard") public class CupboardController { private static final Logger LOG = Logger.getLogger(CupboardController.class.getName()); private final CupboardService cupboardService; private final AuthService authService; /** * Create a cupboard controller to receive REST signals * * @param cupboardService The Data Access Object */ public CupboardController(CupboardService cupboardService, AuthService authService) { this.cupboardService = cupboardService; this.authService = authService; } /** * Creates a Need with the provided object * * @param params The need to create * @return OK response and the need if it was successful, * CONFLICT if another need with the same name exists * UNPROCESSABLE_ENTITY if the need contains bad data * INTERNAL_SERVER_ERROR otherwise */ @PostMapping("") public ResponseEntity createNeed(@RequestBody Map params, @RequestHeader("jelly-api-key") String key) { LOG.log(Level.INFO, "POST /cupboard body={0}", params); String name = (String) params.get("name"); String image = (String) params.get("image"); String location = (String) params.get("location"); double maxGoal; try { maxGoal = ((Number) params.get("maxGoal")).doubleValue(); } catch (NullPointerException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>("Required fields cannot be blank", HttpStatus.BAD_REQUEST); } boolean urgent = (Boolean) params.get("urgent"); String description = (String) params.get("description"); Need.GoalType goalType = GoalType.valueOf((String) params.get("type")); try { authService.keyHasAccessToCupboard(key); Need need = cupboardService.createNeed(name, image, location, maxGoal, goalType, urgent, description); return new ResponseEntity<>(need, HttpStatus.OK); } catch (DuplicateKeyException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.CONFLICT); } catch (IllegalArgumentException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } catch (IllegalAccessException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Responds to the GET request for all {@linkplain Need needs} * * @return ResponseEntity with array of {@link Need needs} objects (may be empty) * and * HTTP status of OK
* ResponseEntity with HTTP status of INTERNAL_SERVER_ERROR otherwise */ @GetMapping("") public ResponseEntity getNeeds() { LOG.info("GET /cupboard"); try { Need[] needs = cupboardService.getNeeds(); return new ResponseEntity<>(needs, HttpStatus.OK); } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Responds to the GET request for all {@linkplain Need need} whose name contains * the text in name * * @param name The name parameter which contains the text used to find the {@link Need need} * * @return ResponseEntity with array of {@link Need need} objects (may be empty) and * HTTP status of OK
* ResponseEntity with HTTP status of INTERNAL_SERVER_ERROR otherwise *

*/ @GetMapping("/") public ResponseEntity searchNeeds(@RequestParam String name) { LOG.info("GET /cupboard/?name="+name); try { Need[] needs = cupboardService.searchNeeds(name); return new ResponseEntity<>(needs, HttpStatus.OK); } catch (IOException ex) { LOG.log(Level.SEVERE,ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Responds to the GET request for a {@linkplain Need need} for the given id * * @param id The id used to locate the {@link Need need} * * @return ResponseEntity with {@link Need need} object and HTTP status of OK if found
* ResponseEntity with HTTP status of NOT_FOUND if not found
*/ @GetMapping("/{id}") public ResponseEntity getNeed(@PathVariable int id) { LOG.log(Level.INFO, "GET /cupboard/{0}", id); try { Need need = cupboardService.getNeed(id); if (need != null) { return new ResponseEntity<>(need, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Updates a Need with the provided one * * @param need The need to update * @return OK response and the need if it was successful, or INTERNAL_SERVER_ERROR if there was an issue */ @PutMapping("/{id}") public ResponseEntity updateNeed(@RequestBody Need need, @PathVariable int id, @RequestHeader("jelly-api-key") String key) { LOG.log(Level.INFO, "PUT /cupboard/{0} body={1}", of(id, need)); try { authService.keyHasAccessToCupboard(key); Need updatedNeed = cupboardService.updateNeed(need, id); if (updatedNeed != null) { return new ResponseEntity<>(need, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } catch (IllegalArgumentException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } catch (IllegalAccessException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Checks out a need by checkoutAmount * * @param data JSON object with parameters needID and amount * @param key Key used to authenticate user * @return OK if successful, other statuses if failure */ @PutMapping("/checkout") public ResponseEntity checkoutNeeds(@RequestBody List> data, @RequestHeader("jelly-api-key") String key) { LOG.log(Level.INFO, "PUT /cupboard/checkout body={0}", data); try { authService.keyIsValid(key); for (Map map : data) { int needID = map.get("needID"); if (cupboardService.getNeed(needID) == null) { return new ResponseEntity<>("One or more needs are invalid, please refresh.", HttpStatus.BAD_REQUEST); } } for (Map map : data) { int needID = map.get("needID"); int checkoutAmount = map.get("quantity"); cupboardService.checkoutNeed(needID, checkoutAmount, key); } return new ResponseEntity<>(HttpStatus.OK); } catch (IllegalArgumentException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } catch (IllegalAccessException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } /** * Deletes a single need from the cupboard using the Need's id * * @param id The need's ID * @return OK if the need was deleted, NOT_FOUND if the need was not found, or INTERNAL_SERVER_ERROR if an error occurred */ @DeleteMapping("/{id}") public ResponseEntity deleteNeed(@PathVariable int id, @RequestHeader("jelly-api-key") String key) { LOG.log(Level.INFO, "DELETE /cupboard/{0}", id); try { authService.keyHasAccessToCupboard(key); Need need = cupboardService.getNeed(id); if (cupboardService.deleteNeed(id)) { return new ResponseEntity<>(need, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } catch (IllegalAccessException ex) { LOG.log(Level.WARNING, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.UNAUTHORIZED); } catch (IOException ex) { LOG.log(Level.SEVERE, ex.getLocalizedMessage()); return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } private Object[] of(Object ...params) { return params; } }