package com.aemreunal.controller.api; /* * *********************** * * 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.JSONObject; import java.util.LinkedHashSet; import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; 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.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.aemreunal.config.GlobalSettings; import com.aemreunal.domain.*; import com.aemreunal.exception.MalformedRequestException; import com.aemreunal.exception.connection.ConnectionNotFoundException; import com.aemreunal.exception.imageStorage.ImageLoadException; import com.aemreunal.exception.textStorage.TextLoadException; import com.aemreunal.service.APIService; import com.aemreunal.service.ScenarioService; @Controller @RequestMapping(GlobalSettings.API_PATH_MAPPING) public class APIController { @Autowired private APIService apiService; @Autowired private ScenarioService scenarioService; // TODO get entire project info via secret // Update the database on client app launch // 1) Get available regions // 1.1) If new regions are present, get them, their beacons, their images // 2) Check for updates to existing regions // 2.1) If updates are found, download them (like 1.1). /* * Project ID JSON structure: * { * "projectId": <project ID>, * "secret": <project Secret> * } */ @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_PROJECT_QUERY_PATH_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<JSONObject> queryForProject(@RequestBody JSONObject idJson) { verifyProjectQueryRequest(idJson); JSONObject project = getProject(idJson); return new ResponseEntity<JSONObject>(project, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_REGION_QUERY_PATH_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<LinkedHashSet<JSONObject>> queryForRegions(@RequestBody JSONObject idJson) { verifyProjectQueryRequest(idJson); LinkedHashSet<JSONObject> regions = getRegionsOfProject(idJson); return new ResponseEntity<LinkedHashSet<JSONObject>>(regions, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_CONNECTION_QUERY_PATH_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<LinkedHashSet<JSONObject>> queryForConnections(@RequestBody JSONObject idJson) { verifyProjectQueryRequest(idJson); LinkedHashSet<JSONObject> regions = getConnectionsOfProject(idJson); return new ResponseEntity<LinkedHashSet<JSONObject>>(regions, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_BEACON_QUERY_PATH_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<LinkedHashSet<JSONObject>> queryForBeacons(@RequestBody JSONObject idJson, @PathVariable Long regionId) { verifyProjectQueryRequest(idJson); LinkedHashSet<JSONObject> beacons = getBeaconsOfRegion(idJson, regionId); return new ResponseEntity<LinkedHashSet<JSONObject>>(beacons, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_REGION_IMG_QUERY_PATH_MAPPING, produces = MediaType.IMAGE_JPEG_VALUE) public ResponseEntity<byte[]> queryForRegionImage(@RequestBody JSONObject idJson, @PathVariable Long regionId) throws ImageLoadException { verifyProjectQueryRequest(idJson); byte[] regionImage = getRegionImage(idJson, regionId); if (regionImage == null) { return new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST); } return new ResponseEntity<byte[]>(regionImage, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_CONNECTION_IMG_QUERY_PATH_MAPPING, produces = MediaType.IMAGE_JPEG_VALUE) public ResponseEntity<byte[]> queryForConnectionImage(@RequestBody JSONObject idJson, @PathVariable Long connectionId) throws ImageLoadException, ConnectionNotFoundException { verifyProjectQueryRequest(idJson); byte[] connectionImage = getConnectionImage(idJson, connectionId); if (connectionImage == null) { return new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST); } return new ResponseEntity<byte[]>(connectionImage, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_BEACON_INFO_QUERY_PATH_MAPPING, produces = MediaType.TEXT_HTML_VALUE) public ResponseEntity<String> queryForBeaconLocationInfo(@RequestBody JSONObject idJson, @PathVariable Long regionId, @PathVariable Long beaconId) { verifyProjectQueryRequest(idJson); String locationInfo = getBeaconLocationInfo(idJson, regionId, beaconId); if (locationInfo == null) { return new ResponseEntity<String>(HttpStatus.BAD_REQUEST); } return new ResponseEntity<String>(locationInfo, HttpStatus.OK); } /* * Beacon query JSON example: * { * "uuid": <beacon UUID> * "major": <beacon Major> * "minor": <beacon Minor> * "secret": <project Secret> * } */ // @RequestMapping(method = RequestMethod.POST, value = GlobalSettings.API_BEACON_QUERY_PATH_MAPPING, produces = MediaType.APPLICATION_JSON_VALUE) // public ResponseEntity<JSONObject> queryForScenario(@RequestBody JSONObject beaconQueryJson) { // verifyBeaconQueryRequest(beaconQueryJson); // Scenario scenario = getScenario(beaconQueryJson); // return new ResponseEntity<JSONObject>(scenario.generateQueryResponse(), HttpStatus.OK); // } private JSONObject getProject(JSONObject idJson) { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); Project project = apiService.queryForProject(projectId, secret); return project.getQueryResponse(); } private LinkedHashSet<JSONObject> getRegionsOfProject(JSONObject idJson) { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); Set<Region> regions = apiService.queryForRegionsOfProject(projectId, secret); return regions.stream() .sorted() .map(Region::getQueryResponse) .collect(Collectors.toCollection(LinkedHashSet::new)); } private LinkedHashSet<JSONObject> getBeaconsOfRegion(JSONObject idJson, Long regionId) { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); // Getting LazyInitException // Region region = apiService.queryForRegionOfProject(projectId, secret, regionId); // Set<Region> regions = apiService.queryForRegionsOfProject(projectId, secret); // Region region = regions.stream() // .filter(regionVar -> regionVar.getRegionId().equals(regionId)) // .findFirst() // .get(); return apiService.queryForBeaconsOfRegion(projectId, secret, regionId) .stream() .sorted() .map(Beacon::getQueryResponse) .collect(Collectors.toCollection(LinkedHashSet::new)); } private LinkedHashSet<JSONObject> getConnectionsOfProject(JSONObject idJson) { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); Set<Connection> connections = apiService.queryForConnections(projectId, secret); return connections.stream() .map(Connection::getQueryResponse) .collect(Collectors.toCollection(LinkedHashSet::new)); } private byte[] getRegionImage(JSONObject idJson, Long regionId) throws ImageLoadException { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); return apiService.queryForImageOfRegion(projectId, secret, regionId); } private byte[] getConnectionImage(JSONObject idJson, Long connectionId) throws ImageLoadException, ConnectionNotFoundException { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); return apiService.queryForImageOfConnection(projectId, secret, connectionId); } private String getBeaconLocationInfo(JSONObject idJson, Long regionId, Long beaconId) { Long projectId = Long.valueOf(idJson.get("projectId").toString()); String secret = idJson.get("secret").toString().toUpperCase(); try { return apiService.queryForLocationInfoOfBeacon(projectId, secret, regionId, beaconId); } catch (TextLoadException e) { // Text can't be loaded or there is no text return null; } } private Scenario getScenario(JSONObject beaconQueryJson) { String uuid = beaconQueryJson.get("uuid").toString().toUpperCase(); Integer major = Integer.valueOf(beaconQueryJson.get("major").toString()); Integer minor = Integer.valueOf(beaconQueryJson.get("minor").toString()); String secret = beaconQueryJson.get("secret").toString().toUpperCase(); return scenarioService.queryForScenario(uuid, major, minor, secret); } private void verifyProjectQueryRequest(JSONObject projectQueryJson) { if (!projectQueryJson.containsKey("projectId") || !projectQueryJson.containsKey("secret")) { throw new MalformedRequestException(); } } private void verifyBeaconQueryRequest(JSONObject beaconQueryJson) { if (!beaconQueryJson.containsKey("uuid") || !beaconQueryJson.containsKey("major") || !beaconQueryJson.containsKey("minor") || !beaconQueryJson.containsKey("secret")) { throw new MalformedRequestException(); } } }