InstituteFilesServiceImpl.java

/**
 * Copyright 2016 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.genesys.server.service.impl;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
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.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
import org.genesys.server.exception.NotFoundElement;
import org.genesys.server.model.genesys.Accession;
import org.genesys.server.model.impl.FaoInstitute;
import org.genesys.server.service.InstituteFilesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Security checks & co.
 */
@Service
public class InstituteFilesServiceImpl implements InstituteFilesService {


	public static final Logger LOG = LoggerFactory.getLogger(InstituteFilesServiceImpl.class);

	private static final String ACCESSION_GALLERY_TITLE_FORMAT = "%1s image gallery";

	private static final String ACCESSION_GALLERY_DESCRIPTION = null;

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private ImageGalleryService imageGalleryService;

	/**
	 * @param instCode INSTCODE
	 * @return
	 */
	private static final Path getGalleriesPrefix(final String instCode) {
		return Paths.get(REPOSITORY_INSTITUTE_PREFIX, instCode, REPOSITORY_INSTITUTE_ACCESSIONFILES);
	}

	private static final Path getGalleryPath(final FaoInstitute institute, final Accession accession) throws InvalidRepositoryPathException {
		return getGalleryPath(institute.getCode(), accession.getAccessionNumber());
	}
	
	public static final Path getGalleryPath(final String instCode, final String acceNumb) throws InvalidRepositoryPathException {
		if (StringUtils.contains(acceNumb, "/")) {
			throw new InvalidRepositoryPathException("ACCENUMB contains /, cannot create gallery for " + acceNumb);
		}
		
		return getGalleriesPrefix(instCode).resolve(acceNumb);
	}

	@Override
	public Page<ImageGallery> listImageGalleries(FaoInstitute institute, Pageable pageable) throws InvalidRepositoryPathException {
		return imageGalleryService.listImageGalleries(getGalleriesPrefix(institute.getCode()), pageable);
	}

	@Override
	public ImageGallery loadImageGallery(final FaoInstitute institute, final Accession accession) throws InvalidRepositoryPathException {
		final Path path = getGalleryPath(institute, accession);
		return this.imageGalleryService.loadImageGallery(path);
	}

	@Override
	@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')")
	public ImageGallery createImageGallery(FaoInstitute institute, Accession accession) throws InvalidRepositoryPathException {
		return this.imageGalleryService.createImageGallery(getGalleryPath(institute.getCode(), accession.getAccessionNumber()), String.format(ACCESSION_GALLERY_TITLE_FORMAT, accession.getAccessionNumber()), ACCESSION_GALLERY_DESCRIPTION);
	}

	@Override
	@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')")
	@Transactional(readOnly = true)
	public RepositoryImage getImage(final FaoInstitute institute, final Accession accession, final UUID uuid) throws NoSuchRepositoryFileException, InvalidRepositoryPathException {
		final RepositoryFile repositoryFile = this.repositoryService.getFile(uuid);

		if (!repositoryFile.getFolder().getFolderPath().equals(getGalleryPath(institute, accession))) {
			LOG.warn("{}!={}", repositoryFile.getFolder().getFolderPath(), getGalleryPath(institute, accession));
			throw new NotFoundElement("No such thing");
		}

		// TODO Fix the path before returning
		return (RepositoryImage) repositoryFile;
	}

	@Override
	@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')")
	@Transactional(readOnly = false)
	public RepositoryImage updateImageMetadata(final FaoInstitute institute, Accession accession, final UUID uuid, final RepositoryImage imageData) throws NoSuchRepositoryFileException, InvalidRepositoryPathException {
		final RepositoryFile repositoryFile = this.repositoryService.getFile(uuid);
		if (!repositoryFile.getFolder().getFolderPath().equals(getGalleryPath(institute, accession))) {
			LOG.warn("{}!={}", repositoryFile.getFolder().getFolderPath(), getGalleryPath(institute, accession));
			throw new NotFoundElement("No such thing");
		}
		imageData.setUuid(repositoryFile.getUuid());
		imageData.setVersion(repositoryFile.getVersion());
		return this.repositoryService.updateMetadata(imageData);
	}

	@Override
	@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#institute, 'WRITE') or hasPermission(#institute, 'CREATE')")
	public byte[] getFileBytes(final FaoInstitute institute, final Accession accession, final RepositoryImage repositoryImage) throws NoSuchRepositoryFileException, IOException {
		return this.repositoryService.getFileBytes(repositoryImage);
	}

}