SubsetApiService.java

/*
 * Copyright 2024 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.api.v2.facade;

import com.fasterxml.jackson.annotation.JsonUnwrapped;
import org.genesys.server.api.FilteredPage;
import org.genesys.server.api.v2.model.impl.SubsetAccessionRefDTO;
import org.genesys.server.api.v2.model.impl.SubsetCreatorDTO;
import org.genesys.server.api.v2.model.impl.SubsetDTO;
import org.genesys.server.api.v2.model.impl.SubsetLangDTO;
import org.genesys.server.api.v2.model.impl.TranslatedSubsetDTO;
import org.genesys.server.exception.NotFoundElement;
import org.genesys.server.exception.SearchException;
import org.genesys.server.model.impl.Subset;
import org.genesys.server.model.impl.SubsetLang;
import org.genesys.server.service.ElasticsearchService;
import org.genesys.server.service.ElasticsearchService.TermResult;
import org.genesys.server.service.TranslatorService.TranslatorException;
import org.genesys.server.service.filter.SubsetFilter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public interface SubsetApiService extends APIFilteredTranslatedServiceFacade
	<SubsetDTO, TranslatedSubsetDTO, SubsetLangDTO, Subset, SubsetLang, SubsetFilter> {

	/**
	 * Load AccessionRef list by Subset.
	 *
	 * @param subset the subset
	 * @param page Pageable
	 * @return PageImpl of AccessionRef
	 */
	Page<SubsetAccessionRefDTO> listAccessions(SubsetDTO subset, Pageable page);

	/**
	 * Count published subsets.
	 *
	 * @param filter the filter
	 * @return the number of published subsets
	 */
	long countSubsets(SubsetFilter filter) throws SearchException;

	/**
	 * List current user's subsets matching the filter.
	 *
	 * @param filter filter data
	 * @param page Pageable
	 * @return list of Subset
	 */
	Page<SubsetDTO> listSubsetsForCurrentUser(SubsetFilter filter, Pageable page);

	/**
	 * Load subset with translations.
	 *
	 * @param uuid the uuid
	 * @return the subset
	 */
	TranslatedSubsetDTO loadSubset(UUID uuid);

	/**
	 * Load Subset.
	 *
	 * @param uuid the uuid
	 * @return the subset
	 */
	SubsetDTO getSubset(UUID uuid);

	/**
	 * Load Subset.
	 *
	 * @param uuid the uuid
	 * @param version the version
	 * @return the subset
	 */
	SubsetDTO getSubset(UUID uuid, int version);

	/**
	 * Get terms by filter.
	 * @param filter the subset filter
	 *
	 * @return the term result
	 * @throws SearchException the search exception
	 * @throws IOException the IO exception
	 */
	Map<String, ElasticsearchService.TermResult> getSuggestions(SubsetFilter filter) throws SearchException, IOException;

	/**
	 * Method adding new accessionId to Subset.
	 *
	 * @param input current Subset
	 * @param accessionRefs the accession refs
	 * @return updated Subset in db.
	 */
	Subset addAccessionRefs(SubsetDTO input, @Valid Collection<SubsetAccessionRefDTO> accessionRefs);

	/**
	 * Puts the subset into the Review state to be reviewed by admin.
	 * Admin and the user with MANAGE permission - only.
	 *
	 * @param subset the subset
	 * @return subset in REVIEWING state
	 */
	Subset reviewSubset(SubsetDTO subset);

	/**
	 * Unpublishes published subset.
	 * Admin and the user with MANAGE permission - only.
	 *
	 * @param subset the subset
	 * @return unpublished subset
	 */
	Subset rejectSubset(SubsetDTO subset);

	/**
	 * Validates and publishes an unpublished subset. Admin - only
	 *
	 * @param subset the subset
	 * @return published subset
	 */
	Subset approveSubset(SubsetDTO subset);

	// List<SubsetDTO> listByAccession(AccessionDTO accession);

	/**
	 * Create SubsetCreator for Subset.
	 *
	 * @param subset the Subset
	 * @param input SubsetCreator
	 * @return created SubsetCreator
	 * @throws NotFoundElement throws if don't match the version
	 */
	SubsetCreatorDTO createSubsetCreator(SubsetDTO subset, @Valid SubsetCreatorDTO input) throws NotFoundElement;

	/**
	 * Remove SubsetCreator of Subset.
	 *
	 * @param subset the Subset
	 * @param input SubsetCreator
	 * @return removed SubsetCreator
	 * @throws NotFoundElement throws if don't match the version
	 */
	SubsetCreatorDTO removeSubsetCreator(SubsetDTO subset, SubsetCreatorDTO input) throws NotFoundElement;

	/**
	 * Removes the Subset creator.
	 *
	 * @param subset the Subset
	 * @param subsetCreatorUuid the Subset creator uuid
	 * @return the Subset creator
	 * @throws NotFoundElement the not found element
	 */
	SubsetCreatorDTO removeSubsetCreator(SubsetDTO subset, UUID subsetCreatorUuid) throws NotFoundElement;

	/**
	 * Load Subset by input SubsetCreator.
	 *
	 * @param subsetCreator input SubsetCreator
	 * @return loaded SubsetCreator
	 * @throws NotFoundElement throws if don't match the version
	 */
	SubsetCreatorDTO loadSubsetCreator(SubsetCreatorDTO subsetCreator) throws NotFoundElement;

	/**
	 * Load Subset by input SubsetCreator.
	 *
	 * @param subsetCreatorUuid input SubsetCreator UUID
	 * @return loaded SubsetCreator
	 * @throws NotFoundElement throws if don't match the version
	 */
	SubsetCreatorDTO loadSubsetCreator(UUID subsetCreatorUuid) throws NotFoundElement;

	/**
	 * Load list SubsetCreators by Subset UUID.
	 *
	 * @param subset the Subset
	 * @return List of SubsetCreator
	 * @throws NotFoundElement throws if don't match the version
	 */
	List<SubsetCreatorDTO> listSubsetCreators(SubsetDTO subset) throws NotFoundElement;

	/**
	 * Update Subset creator.
	 *
	 * @param subset the Subset
	 * @param subsetCreator the Subset creator
	 * @return the Subset creator
	 * @throws NotFoundElement the not found element
	 */
	SubsetCreatorDTO updateSubsetCreator(SubsetDTO subset, @Valid SubsetCreatorDTO subsetCreator) throws NotFoundElement;

	/**
	 * Autocomplete creators.
	 *
	 * @param text the text
	 * @return list of matched creators
	 */
	List<SubsetCreatorDTO> autocompleteCreators(String text);


	/**
	 * Rematch subset accessions across all Subsets.
	 */
	void rematchSubsetAccessions();

	/**
	 * Rematch subset accessions for a Subset
	 *
	 * @param subset the subset
	 * @return the subset
	 */
	Subset rematchSubsetAccessions(SubsetDTO subset);

	/**
	 * Schedule re-matching of AccessionRefs in batches
	 * @param accessionRefs the accession refs
	 */
	void batchRematchAccessionRefs(List<SubsetAccessionRefDTO> accessionRefs);

	// /**
	//  * Clear accession references across all Subsets for specified accessions.
	//  *
	//  * @param accessions the accessions
	//  * @return the int
	//  */
	// int clearAccessionRefs(Collection<AccessionDTO> accessions);

	/**
	 * Sets the accessions.
	 *
	 * @param input the input
	 * @param accessionRefs the accessions refs
	 * @return the subset
	 */
	Subset setAccessionRefs(SubsetDTO input, @Valid Collection<SubsetAccessionRefDTO> accessionRefs);

	/**
	 * Generate Excel file with MCPD passport data for provided subset.
	 *
	 * @param subset the subset
	 * @param outputStream the stream
	 */
	void writeXlsxMCPD(SubsetDTO subset, OutputStream outputStream) throws IOException;

	/**
	 * Method creating a new version of Subset based on an existing published Subset.
	 *
	 * @param source the source
	 * @return saved Subset in db.
	 */
	Subset createNewVersion(@Valid SubsetDTO source);

	class SubsetsWithSuggestions extends FilteredPage<TranslatedSubsetDTO, SubsetFilter> {

		public Map<String, ElasticsearchService.TermResult> suggestions;

		public SubsetsWithSuggestions(String filterCode, SubsetFilter filter, Page<TranslatedSubsetDTO> data) {
			super(filterCode, filter, data);
		}

		public static SubsetsWithSuggestions from(String filterCode, SubsetFilter filter, Page<TranslatedSubsetDTO> data, Map<String, TermResult> suggestions) {
			SubsetsWithSuggestions res = new SubsetsWithSuggestions(filterCode, filter, data);
			res.suggestions = suggestions;
			return res;
		}
	}

	@PreAuthorize("hasRole('VETTEDUSER') || hasRole('ADMINISTRATOR') || hasRole('CONTENTMANAGER')")
	SubsetLangDTO machineTranslate(UUID uuid, String targetLang) throws TranslatorException;


	// /**
	//  * Update existing Subsets and accession refs from old FAO WIEWS Institute to the new Institute.
	//  * This updates accession.instCode and accession.institute in the database.
	//  *
	//  * @param currentInstitute current {@link FaoInstitute}
	//  * @param newInstitute new institute
	//  * @throws RuntimeException if the new institute already has Subsets
	//  * @return number of updated {@link Subset} records
	//  */
	// long changeInstitute(FaoInstituteDTO currentInstitute, FaoInstituteDTO newInstitute);

	SubsetDTO uploadAccessions(UUID uuid, int version, char separator, char quotechar, MultipartFile file) throws IOException;
}