FilesServiceImpl.java
/*
* Copyright 2019 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gringlobal.compatibility.service.impl;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFileException;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.model.RepositoryImage;
import org.genesys.filerepository.service.BytesStorageService;
import org.genesys.filerepository.service.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
import org.genesys.filerepository.service.impl.RepositoryServiceImpl;
import org.gringlobal.compatibility.service.FilesService;
import org.gringlobal.model.AccessionInvAttach;
import org.gringlobal.service.InventoryAttachmentService;
import org.gringlobal.service.InventoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Slf4j
public class FilesServiceImpl implements FilesService {
@Autowired
@Lazy
private InventoryService inventoryService;
@Autowired
@Lazy
private InventoryAttachmentService attachmentFileService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ImageGalleryService imageGalleryService;
@Autowired
private BytesStorageService byteStorageService;
@Value("${file.repository.image.thumbnailSizes}")
private int[] thumbnailSizes;
@Override
@PreAuthorize("isAuthenticated()")
@Transactional
public String upload(String fullPath, byte[] imageBytes, boolean createThumbnail, boolean overwriteIfExists) throws InvalidRepositoryPathException, InvalidRepositoryFileDataException, IOException {
Path filePath = Paths.get("/", fullPath).normalize().toAbsolutePath();
log.info("Uploading {}b to {} {}", imageBytes.length, filePath.getParent().toAbsolutePath(), filePath.getFileName());
log.info("Creating thumbnail={} overwrite={}", createThumbnail, overwriteIfExists);
RepositoryFile metaData = new RepositoryFile();
String detectedContentType = null;
if (filePath.getFileName().toString().toLowerCase().endsWith(".png")) {
detectedContentType = MediaType.IMAGE_PNG_VALUE;
} else if (filePath.getFileName().toString().toLowerCase().endsWith(".jpeg")) {
detectedContentType = MediaType.IMAGE_JPEG_VALUE;
} else if (filePath.getFileName().toString().toLowerCase().endsWith(".jpg")) {
detectedContentType = MediaType.IMAGE_JPEG_VALUE;
} else if (filePath.getFileName().toString().toLowerCase().endsWith(".gif")) {
detectedContentType = MediaType.IMAGE_GIF_VALUE;
}
var contentType = detectedContentType;
RepositoryFile repositoryFile = null;
//
// Create or update *Attach records
//
if (Objects.equals("AIA", filePath.getName(0).toString()) && filePath.getNameCount() == 6) {
// AccessionInvAttach
// /AIA/Abarema/74/35174/35359/medium-40627.jpg
var inventoryId = Long.parseLong(filePath.getName(4).toString());
log.info("Have attachment {} for inventory id={}", filePath, inventoryId);
var inventory = inventoryService.get(inventoryId); // Throws
repositoryFile = repositoryService.addFile(filePath.getParent().toAbsolutePath(), filePath.getFileName().toString(), contentType, imageBytes, metaData);
log.warn("Added type {} to repository", repositoryFile.getClass());
AccessionInvAttach existingAttach = attachmentFileService.findAttachment(inventory, filePath);
if (existingAttach != null) {
log.info("Updating existing AccessionInvAttach {}", existingAttach);
if (existingAttach.getRepositoryFile() != null) {
try {
repositoryService.removeFile(existingAttach.getRepositoryFile());
} catch (NoSuchRepositoryFileException | IOException e) {
log.warn("Could not remove repository file of existing attachment: {}", e.getMessage());
}
}
existingAttach.setRepositoryFile(repositoryFile);
existingAttach.setContentType(detectedContentType);
attachmentFileService.update(existingAttach);
} else {
log.info("Creating new AccessionInvAttach for inventory {}", inventory);
var newAttach = new AccessionInvAttach();
newAttach.setInventory(inventory);
newAttach.setRepositoryFile(repositoryFile);
newAttach.setContentType(detectedContentType);
newAttach.setVirtualPath(filePath.toString());
newAttach.setTitle(filePath.getFileName().toString());
newAttach = attachmentFileService.create(newAttach);
}
} else {
// Allow uploads for non-/AIA/ folders
repositoryFile = repositoryService.addFile(filePath.getParent().toAbsolutePath(), filePath.getFileName().toString(), contentType, imageBytes, metaData);
log.warn("Added type {} to repository", repositoryFile.getClass());
}
if (createThumbnail) {
// Thumbnails requested, it's an image gallery
ImageGallery imageGallery = imageGalleryService.createImageGallery(filePath.getParent().toAbsolutePath(), null, null);
imageGalleryService.ensureThumbnails(imageGallery);
}
// CT Wizard checks if the return message contains the file name
return Path.of(repositoryFile.getFolder().getPath(), repositoryFile.getOriginalFilename()).toString();
}
@Override
@PreAuthorize("isAuthenticated()")
public byte[] download(String fullPath) throws NoSuchRepositoryFileException, InvalidRepositoryPathException, IOException {
Path filePath = Paths.get("/", fullPath);
log.info("Getting {} {}", filePath.getParent().toAbsolutePath(), filePath.getFileName());
RepositoryFile repositoryFile = repositoryService.getFile(filePath.getParent().toAbsolutePath(), filePath.getFileName().toString());
return repositoryService.getFileBytes(repositoryFile);
}
@Override
@PreAuthorize("isAuthenticated()")
public boolean delete(String fullPath) throws NoSuchRepositoryFileException, InvalidRepositoryPathException, IOException {
Path filePath = Paths.get("/", fullPath);
log.info("Deleting {} {}", filePath.getParent().toAbsolutePath(), filePath.getFileName());
RepositoryFile repositoryFile = repositoryService.getFile(filePath.getParent().toAbsolutePath(), filePath.getFileName().toString());
repositoryService.removeFile(repositoryFile);
return true;
}
@Override
public byte[] thumbnail(String fullPath) throws NoSuchRepositoryFileException, InvalidRepositoryPathException, IOException {
Path filePath = Paths.get("/", fullPath);
Path imagePath = Paths.get(filePath.getParent().toString(), filePath.getFileName().toString().replace("_thumbnail", ""));
log.info("Thumb path {}", imagePath.toAbsolutePath());
RepositoryFile repositoryImage = repositoryService.getFile(imagePath.getParent(), imagePath.getFileName().toString());
if (repositoryImage instanceof RepositoryImage) {
Path thumbPath = RepositoryServiceImpl.getFullThumbnailsPath((RepositoryImage) repositoryImage);
// Take the middle-sized thumbnail :-)
Path thumbFile = Paths.get(thumbPath.toString(), thumbnailSizes[thumbnailSizes.length/2] + "x" + thumbnailSizes[thumbnailSizes.length/2] + ".jpg");
return byteStorageService.get(thumbFile);
}
log.info("No thumb in {} for {}", imagePath.getParent(), imagePath.getFileName());
throw new NoSuchRepositoryFileException("No image for this path.");
}
}