package org.jhipster.health.web.rest;
import com.codahale.metrics.annotation.Timed;
import org.jhipster.health.domain.Weight;
import org.jhipster.health.repository.UserRepository;
import org.jhipster.health.repository.WeightRepository;
import org.jhipster.health.repository.search.WeightSearchRepository;
import org.jhipster.health.security.AuthoritiesConstants;
import org.jhipster.health.security.SecurityUtils;
import org.jhipster.health.web.rest.vm.WeightByPeriod;
import org.jhipster.health.web.rest.util.HeaderUtil;
import org.jhipster.health.web.rest.util.PaginationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.inject.Inject;
import javax.validation.Valid;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
/**
* REST controller for managing Weight.
*/
@RestController
@RequestMapping("/api")
public class WeightResource {
private final Logger log = LoggerFactory.getLogger(WeightResource.class);
@Inject
private WeightRepository weightRepository;
@Inject
private WeightSearchRepository weightSearchRepository;
@Inject
private UserRepository userRepository;
/**
* POST /weights : Create a new weight.
*
* @param weight the weight to create
* @return the ResponseEntity with status 201 (Created) and with body the new weight, or with status 400 (Bad Request) if the weight has already an ID
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@RequestMapping(value = "/weights",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<Weight> createWeight(@Valid @RequestBody Weight weight) throws URISyntaxException {
log.debug("REST request to save Weight : {}", weight);
if (weight.getId() != null) {
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("weight", "idexists", "A new weight cannot already have an ID")).body(null);
}
if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
log.debug("No user passed in, using current user: {}", SecurityUtils.getCurrentUserLogin());
weight.setUser(userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).get());
}
if (weight.getTimestamp() == null) {
// todo: get user's timezone from preferences
weight.setTimestamp(ZonedDateTime.now());
}
Weight result = weightRepository.save(weight);
weightSearchRepository.save(result);
return ResponseEntity.created(new URI("/api/weights/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert("weight", result.getId().toString()))
.body(result);
}
/**
* PUT /weights : Updates an existing weight.
*
* @param weight the weight to update
* @return the ResponseEntity with status 200 (OK) and with body the updated weight,
* or with status 400 (Bad Request) if the weight is not valid,
* or with status 500 (Internal Server Error) if the weight couldnt be updated
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@RequestMapping(value = "/weights",
method = RequestMethod.PUT,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<Weight> updateWeight(@Valid @RequestBody Weight weight) throws URISyntaxException {
log.debug("REST request to update Weight : {}", weight);
if (weight.getId() == null) {
return createWeight(weight);
}
Weight result = weightRepository.save(weight);
weightSearchRepository.save(result);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert("weight", weight.getId().toString()))
.body(result);
}
/**
* GET /weights : get all the weights.
*
* @param pageable the pagination information
* @return the ResponseEntity with status 200 (OK) and the list of weights in body
* @throws URISyntaxException if there is an error to generate the pagination HTTP headers
*/
@RequestMapping(value = "/weights",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<List<Weight>> getAllWeights(Pageable pageable)
throws URISyntaxException {
log.debug("REST request to get a page of Weights");
Page<Weight> page;
if (SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
page = weightRepository.findAllByOrderByTimestampDesc(pageable);
} else {
page = weightRepository.findByUserIsCurrentUser(pageable);
}
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/weights");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
/**
* GET /weight-by-days : get all the weigh-ins for last x days.
*/
@RequestMapping(value = "/weight-by-days/{days}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<WeightByPeriod> getByDays(@PathVariable int days) {
ZonedDateTime rightNow = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime daysAgo = rightNow.minusDays(days);
List<Weight> weighIns = weightRepository.findAllByTimestampBetweenOrderByTimestampDesc(daysAgo, rightNow);
WeightByPeriod response = new WeightByPeriod("Last " + days + " Days", filterByUser(weighIns));
return new ResponseEntity<>(response, HttpStatus.OK);
}
/**
* GET /bp-by-days -> get all the blood pressure readings for a particular month.
*/
@RequestMapping(value = "/weight-by-month/{date}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<WeightByPeriod> getByMonth(@PathVariable @DateTimeFormat(pattern = "yyyy-MM") YearMonth date) {
LocalDate firstDay = date.atDay(1);
LocalDate lastDay = date.atEndOfMonth();
ZoneId timezone = ZoneId.of("Z");
List<Weight> weighIns = weightRepository.
findAllByTimestampBetweenOrderByTimestampDesc(firstDay.atStartOfDay(timezone),
lastDay.plusDays(1).atStartOfDay(timezone));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM");
String yearAndMonth = fmt.format(firstDay);
WeightByPeriod response = new WeightByPeriod(yearAndMonth, filterByUser(weighIns));
return new ResponseEntity<>(response, HttpStatus.OK);
}
private List<Weight> filterByUser(List<Weight> readings) {
Stream<Weight> userReadings = readings.stream()
.filter(bp -> bp.getUser().getLogin().equals(SecurityUtils.getCurrentUserLogin()));
return userReadings.collect(Collectors.toList());
}
/**
* GET /weights/:id : get the "id" weight.
*
* @param id the id of the weight to retrieve
* @return the ResponseEntity with status 200 (OK) and with body the weight, or with status 404 (Not Found)
*/
@RequestMapping(value = "/weights/{id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<Weight> getWeight(@PathVariable Long id) {
log.debug("REST request to get Weight : {}", id);
Weight weight = weightRepository.findOne(id);
return Optional.ofNullable(weight)
.map(result -> new ResponseEntity<>(
result,
HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
/**
* DELETE /weights/:id : delete the "id" weight.
*
* @param id the id of the weight to delete
* @return the ResponseEntity with status 200 (OK)
*/
@RequestMapping(value = "/weights/{id}",
method = RequestMethod.DELETE,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<Void> deleteWeight(@PathVariable Long id) {
log.debug("REST request to delete Weight : {}", id);
weightRepository.delete(id);
weightSearchRepository.delete(id);
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("weight", id.toString())).build();
}
/**
* SEARCH /_search/weights?query=:query : search for the weight corresponding
* to the query.
*
* @param query the query of the weight search
* @param pageable the pagination information
* @return the result of the search
* @throws URISyntaxException if there is an error to generate the pagination HTTP headers
*/
@RequestMapping(value = "/_search/weights",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<List<Weight>> searchWeights(@RequestParam String query, Pageable pageable)
throws URISyntaxException {
log.debug("REST request to search for a page of Weights for query {}", query);
Page<Weight> page = weightSearchRepository.search(queryStringQuery(query), pageable);
HttpHeaders headers = PaginationUtil.generateSearchPaginationHttpHeaders(query, page, "/api/_search/weights");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
}