OutdoorDirectionsController.java
package com.soen390.backend.controller;
import com.soen390.backend.enums.BuildingLocation;
import com.soen390.backend.enums.Campus;
import com.soen390.backend.exception.GoogleMapsDirectionEmptyException;
import com.soen390.backend.exception.GoogleMapsDirectionsApiException;
import com.soen390.backend.object.OutdoorDirectionResponse;
import com.soen390.backend.enums.TransportMode;
import com.soen390.backend.service.GoogleMapsService;
import com.soen390.backend.service.ShuttleOutdoorDirectionsService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import java.util.Locale;
import java.util.Map;
@RestController
@RequestMapping("/api/directions/outdoor")
public class OutdoorDirectionsController {
private static final String ERROR_KEY = "error";
private final GoogleMapsService mapsService;
private final ShuttleOutdoorDirectionsService shuttleOutdoorDirectionsService;
public OutdoorDirectionsController(GoogleMapsService mapsService, ShuttleOutdoorDirectionsService shuttleOutdoorDirectionsService) {
this.mapsService = mapsService;
this.shuttleOutdoorDirectionsService = shuttleOutdoorDirectionsService;
}
@GetMapping
public ResponseEntity<Object> getDirections(
@RequestParam String origin,
@RequestParam String destination,
@RequestParam String transportMode,
@RequestParam(required = false) String originBuildingId,
@RequestParam(required = false) String destinationBuildingId) {
TransportMode normalizedTransportMode;
try {
normalizedTransportMode = TransportMode.valueOf(transportMode.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException ex) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid transportMode: " + transportMode, ex);
}
String resolvedOrigin = resolveEndpoint(origin, originBuildingId);
String resolvedDestination = resolveEndpoint(destination, destinationBuildingId);
try {
OutdoorDirectionResponse response =
mapsService.getDirections(resolvedOrigin, resolvedDestination, normalizedTransportMode);
return ResponseEntity.ok(response);
} catch (GoogleMapsDirectionEmptyException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of(ERROR_KEY, e.getMessage()));
} catch (GoogleMapsDirectionsApiException e) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(Map.of(ERROR_KEY, e.getMessage()));
}
}
@GetMapping("/shuttle")
public ResponseEntity<Object> getDirectionsWithShuttle(
@RequestParam String origin,
@RequestParam String destination,
@RequestParam Campus destinationShuttle,
@RequestParam(required = false) String originBuildingId,
@RequestParam(required = false) String destinationBuildingId) {
String resolvedOrigin = resolveEndpoint(origin, originBuildingId);
String resolvedDestination = resolveEndpoint(destination, destinationBuildingId);
try {
OutdoorDirectionResponse response =
shuttleOutdoorDirectionsService.getShuttleOutdoorDirections(
resolvedOrigin, resolvedDestination, destinationShuttle);
return ResponseEntity.ok(response);
} catch (GoogleMapsDirectionEmptyException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of(ERROR_KEY, e.getMessage()));
} catch (GoogleMapsDirectionsApiException e) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(Map.of(ERROR_KEY, e.getMessage()));
}
}
private String resolveEndpoint(String fallbackValue, String buildingId) {
if (buildingId == null || buildingId.isBlank()) {
return fallbackValue;
}
return BuildingLocation.fromId(buildingId).getDirectionsTarget();
}
}