package com.aemreunal.service; /* * *********************** * * Copyright (c) 2015 * * * * This code belongs to: * * * * @author Ahmet Emre Ünal * * S001974 * * * * aemreunal@gmail.com * * emre.unal@ozu.edu.tr * * * * aemreunal.com * * *********************** * */ import java.util.LinkedHashSet; import java.util.List; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import com.aemreunal.config.GlobalSettings; import com.aemreunal.domain.Beacon; import com.aemreunal.domain.Project; import com.aemreunal.domain.Region; import com.aemreunal.exception.imageStorage.ImageDeleteException; import com.aemreunal.exception.imageStorage.ImageLoadException; import com.aemreunal.exception.imageStorage.ImageSaveException; import com.aemreunal.exception.region.MultipartFileReadException; import com.aemreunal.exception.region.RegionNotFoundException; import com.aemreunal.exception.region.WrongFileTypeSubmittedException; import com.aemreunal.helper.ImageProperties; import com.aemreunal.helper.ImageStorage; import com.aemreunal.repository.region.RegionRepo; import com.aemreunal.repository.region.RegionSpecs; @Transactional @Service public class RegionService { @Autowired private RegionRepo regionRepo; @Autowired private ProjectService projectService; @Autowired private ImageStorage imageStorage; /** * Saves/updates the given region. If the region does not exist in the database, * persists it in the database. * * @param username * The username of the owner of the project. * @param projectId * The ID of the project which the region resides in. * @param region * The region to be saved/updated. * * @return The saved/updated region. */ private Region save(String username, Long projectId, Region region) { GlobalSettings.log("Saving region with ID = \'" + region.getRegionId() + "\'"); Project project = projectService.getProject(username, projectId); if (region.getProject() == null) { // Region is created region.setProject(project); } else { // Region is only updated region.markAsUpdated(); } return regionRepo.save(region); } /** * Creates and saves the newly created region, along with its image. * * @param username * The username of the owner of the project. * @param projectId * The ID of the project which the region resides in. * @param region * The region to be created and saved. * @param imageMultipartFile * The image of the region as a {@link org.springframework.web.multipart.MultipartFile * MultipartFile}. * * @return The saved region. * * @throws WrongFileTypeSubmittedException * The file type of the {@link org.springframework.web.multipart.MultipartFile * MultipartFile} file submitted as the region map image is of some other type * than JPEG, GIF, or PNG. * @throws ImageSaveException * If the server is unable to save the region map image. * @throws MultipartFileReadException * If the Multipart file couldn't be read. */ public Region saveNewRegion(String username, Long projectId, Region region, MultipartFile imageMultipartFile) throws WrongFileTypeSubmittedException, ImageSaveException, MultipartFileReadException { GlobalSettings.log("Creating new region for user = \'" + username + "\' and project = \'" + projectId + "\'"); // Region must be saved prior to setting the map image, as the map // image storage in filesystem depends on region and project IDs. region = this.save(username, projectId, region); return setMapImage(username, projectId, region, imageMultipartFile); } /** * Saves the map image (provided with the {@code mapImageInBytes} parameter) to disk * and sets the name of the image file to the region object. If the region already has * an image, it is overwritten. The region is NOT saved. * * @param username * The username of the owner of the project. * @param projectId * The ID of the project to which the region belongs. * @param region * The region to save the image of. * @param imageFile * The image file as a {@link org.springframework.web.multipart.MultipartFile * MultipartFile}. * * @return The updated region object. * * @throws WrongFileTypeSubmittedException * The file type of the {@link org.springframework.web.multipart.MultipartFile * MultipartFile} file submitted as the region map image is of some other type * than JPEG, GIF, or PNG. * @throws ImageSaveException * If the server is unable to save the region map image. * @throws MultipartFileReadException * If the Multipart file couldn't be read. */ private Region setMapImage(String username, Long projectId, Region region, MultipartFile imageFile) throws ImageSaveException, MultipartFileReadException, WrongFileTypeSubmittedException { GlobalSettings.log("Setting map image of region with ID = \'" + region.getRegionId() + "\'"); ImageProperties savedImageProperties = imageStorage.saveImage(projectId, region.getRegionId(), imageFile); region.setImageProperties(savedImageProperties); return this.save(username, projectId, region); } @Transactional(readOnly = true) public List<Region> getAllRegionsOf(String username, Long projectId) { Project project = projectService.getProject(username, projectId); return project.getRegions().stream().collect(Collectors.toList()); } @Transactional(readOnly = true) public Region getRegion(String username, Long projectId, Long regionId) { GlobalSettings.log("Finding region with ID = \'" + regionId + "\'"); Project project = projectService.getProject(username, projectId); Region region = regionRepo.findByRegionIdAndProject(regionId, project); if (region == null) { throw new RegionNotFoundException(regionId); } return region; } /** * Finds the regions conforming to given specifications * * @param projectId * The project ID constraint * @param regionName * The name field constraint * * @return The list of regions conforming to given constraints */ @Transactional(readOnly = true) public List<Region> findRegionsBySpecs(String username, Long projectId, String regionName) { GlobalSettings.log("Finding regions with projectID = \'" + projectId + "\' and name =\'" + regionName + "\'"); Project project = projectService.getProject(username, projectId); List<Region> regions = regionRepo.findAll(RegionSpecs.regionWithSpecification(project.getProjectId(), regionName)); if (regions.size() == 0) { throw new RegionNotFoundException(); } return regions; } @Transactional(readOnly = true) public LinkedHashSet<Beacon> getMembersOfRegion(String username, Long projectId, Long regionId) { Region region = this.getRegion(username, projectId, regionId); return region.getBeacons().stream() .sorted() .collect(Collectors.toCollection(LinkedHashSet::new)); } @Transactional(readOnly = true) public byte[] getMapImage(String username, Long projectId, Long regionId) throws ImageLoadException { GlobalSettings.log("Getting map image of region with ID = \'" + regionId + "\'"); Region region = this.getRegion(username, projectId, regionId); String mapImageFileName = region.getMapImageFileName(); return imageStorage.loadImage(projectId, regionId, mapImageFileName); } public Region markRegionAsUpdated(String username, Long projectId, Long regionId) { Region region = this.getRegion(username, projectId, regionId); region.markAsUpdated(); return regionRepo.save(region); } /** * Deletes the region with the given ID and updates the beacons in the region. * * @param projectId * The ID of the project to delete the beacon from * @param regionId * The ID of the region to delete * * @return Whether the region was deleted or not */ public Region delete(String username, Long projectId, Long regionId) { GlobalSettings.log("Deleting region with ID = \'" + regionId + "\'"); Region region = this.getRegion(username, projectId, regionId); deleteRegionImageFile(username, projectId, region); regionRepo.delete(region); return region; } private void deleteRegionImageFile(String username, Long projectId, Region region) { try { imageStorage.deleteImage(projectId, region.getRegionId(), region.getMapImageFileName()); } catch (ImageDeleteException e) { GlobalSettings.err("WARNING: Image file for user: " + username + ", project: " + projectId + ", region " + region.getRegionId() + ", file name: " + region.getMapImageFileName() + " could not be deleted! " + "May need to be deleted manually!"); } } }