// Copyright © 2015 HSL <https://www.hsl.fi>
// This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses.
package fi.hsl.parkandride.front;
import fi.hsl.parkandride.core.domain.Hub;
import fi.hsl.parkandride.core.domain.HubSearch;
import fi.hsl.parkandride.core.domain.SearchResults;
import fi.hsl.parkandride.core.domain.User;
import fi.hsl.parkandride.core.domain.prediction.HubPredictionResult;
import fi.hsl.parkandride.core.domain.prediction.PredictionRequest;
import fi.hsl.parkandride.core.service.HubService;
import fi.hsl.parkandride.core.service.PredictionService;
import fi.hsl.parkandride.front.geojson.Feature;
import fi.hsl.parkandride.front.geojson.FeatureCollection;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;
import javax.inject.Inject;
import javax.validation.Valid;
import java.util.List;
import static fi.hsl.parkandride.front.UrlSchema.*;
import static fi.hsl.parkandride.front.geojson.FeatureCollection.HUB_TO_FEATURE;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.*;
@RestController
public class HubController {
private final Logger log = LoggerFactory.getLogger(HubController.class);
@Inject
HubService hubService;
@Inject
PredictionService predictionService;
@RequestMapping(method = POST, value = HUBS, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<Hub> createHub(@RequestBody Hub hub, User currentUser, UriComponentsBuilder builder) {
log.info("createHub");
Hub newHub = hubService.createHub(hub, currentUser);
log.info("createHub({})", newHub.id);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(builder.path(HUB).buildAndExpand(newHub.id).toUri());
return new ResponseEntity<>(newHub, headers, CREATED);
}
@RequestMapping(method = GET, value = HUB, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<Hub> getHub(@PathVariable(HUB_ID) long hubId) {
log.info("getHub({})", hubId);
Hub hub = hubService.getHub(hubId);
return new ResponseEntity<>(hub, OK);
}
@RequestMapping(method = GET, value = HUB, produces = GEOJSON)
public ResponseEntity<Feature> getHubAsFeature(@PathVariable(HUB_ID) long hubId) {
log.info("getHubAsFeature({})", hubId);
Hub hub = hubService.getHub(hubId);
return new ResponseEntity<>(HUB_TO_FEATURE.apply(hub), OK);
}
@RequestMapping(method = PUT, value = HUB, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<Hub> updateHub(@PathVariable(HUB_ID) long hubId,
@RequestBody Hub hub,
User currentUser) {
log.info("updateHub({})", hubId);
Hub updated = hubService.updateHub(hubId, hub, currentUser);
return new ResponseEntity<>(updated, OK);
}
@RequestMapping(method = GET, value = HUBS, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<SearchResults<Hub>> findHubs(HubSearch search) {
log.info("findHubs");
SearchResults<Hub> results = hubService.search(search);
return new ResponseEntity<>(results, OK);
}
@RequestMapping(method = GET, value = HUBS, produces = GEOJSON)
public ResponseEntity<FeatureCollection> findHubsAsFeatureCollection(HubSearch search) {
log.info("findHubsAsFeatureCollection");
SearchResults<Hub> results = hubService.search(search);
return new ResponseEntity<>(FeatureCollection.ofHubs(results), OK);
}
@RequestMapping(method = GET, value = HUB_PREDICTION, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<List<HubPredictionResult>> getPrediction(@PathVariable(HUB_ID) long hubId,
@ModelAttribute @Valid PredictionRequest request) {
DateTime time = request.requestedTime();
log.info("getPrediction({}, {})", hubId, time);
final List<HubPredictionResult> results = hubService.getHub(hubId).facilityIds
.stream()
.flatMap(facilityId -> predictionService.getPredictionResultByFacility(facilityId, time).stream())
.collect(groupingBy(result -> result.capacityType.name() + result.usage.name()))
.values().stream()
.map(list -> HubPredictionResult.sumFrom(hubId, list))
.collect(toList());
return new ResponseEntity<>(results, OK);
}
}