SubsetService.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.genesys.server.service;

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

import javax.validation.Valid;

import org.genesys.server.api.FilteredPage;
import org.genesys.server.exception.NotFoundElement;
import org.genesys.server.model.genesys.Accession;
import org.genesys.server.model.impl.FaoInstitute;
import org.genesys.server.model.impl.Subset;
import org.genesys.server.model.impl.SubsetAccessionRef;
import org.genesys.server.model.impl.SubsetCreator;
import org.genesys.server.model.impl.SubsetLang;
import org.genesys.server.service.ElasticsearchService.TermResult;
import org.genesys.server.service.SubsetTranslationService.TranslatedSubset;
import org.genesys.server.service.filter.SubsetFilter;
import org.genesys.server.exception.SearchException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.fasterxml.jackson.annotation.JsonUnwrapped;

/**
 * @author Maxym Borodenko
 */
public interface SubsetService extends FilteredTranslatedCRUDService<Subset, SubsetLang, SubsetTranslationService.TranslatedSubset, SubsetFilter> {

    /**
     * List published subsets matching the filter.
     *
     * @param filter filter data
     * @param page Pageable
     * @return list of Subset
     */
    Page<Subset> list(SubsetFilter filter, Pageable page) throws SearchException;

	/**
	 * Load AccessionRef list by Subset.
	 *
	 * @param subset the subset
	 * @param page Pageable
	 * @return PageImpl of AccessionRef
	 */
	Page<SubsetAccessionRef> listAccessions(Subset 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<Subset> listSubsetsForCurrentUser(SubsetFilter filter, Pageable page);

    /**
     * Load subset based on identifiers and version provided in the input.
     *
     * @param input query by example
     * @return subset loaded from the database
     */
    Subset loadSubset(Subset input);
    
    /**
     * Load subset.
     *
     * @param uuid the uuid
     * @return the subset
     */
    Subset loadSubset(UUID uuid);
    
    /**
     * Load subset in requested language.
     *
     * @param uuid the uuid
     * @return the subset
     */
    TranslatedSubset loadTranslated(UUID uuid);

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

    /**
     * Load Subset.
     *
     * @param uuid the uuid
     * @param version the version
     * @return the subset
     */
    Subset 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;

    /**
     * Remove subset.
     *
     * @param subset subset
     * @return removed subset
     */
    Subset delete(Subset subset);

    /**
     * Method adding new accessionId to Subset.
     *
     * @param input current Subset
     * @param accessionRefs the accession refs
     * @return updated Subset in db.
     */
    Subset addAccessionRefs(Subset input, @Valid Collection<SubsetAccessionRef> 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(Subset subset);

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

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

    List<Subset> listByAccession(Accession accession);

    /**
     * Create SubsetCreator for Subset.
     *
     * @param subset the Subset
     * @param input SubsetCreator
     * @return created SubsetCreator
     * @throws NotFoundElement throws if don't match the version
     */
    SubsetCreator createSubsetCreator(Subset subset, @Valid SubsetCreator 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
     */
    SubsetCreator removeSubsetCreator(Subset subset, SubsetCreator 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
     */
    SubsetCreator removeSubsetCreator(Subset subset, UUID subsetCreatorUuid) throws NotFoundElement;

    /**
     * Load list SubsetCreators by Subset.
     *
     * @param subset The Subset
     * @return List of Subset creators
     */
    List<SubsetCreator> listSubsetCreators(Subset subset);

    /**
     * Load Subset by input SubsetCreator.
     *
     * @param subsetCreator input SubsetCreator
     * @return loaded SubsetCreator
     * @throws NotFoundElement throws if don't match the version
     */
    SubsetCreator loadSubsetCreator(SubsetCreator 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
     */
    SubsetCreator loadSubsetCreator(UUID subsetCreatorUuid) throws NotFoundElement;

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

    /**
     * Autocomplete creators.
     *
     * @param text the text
     * @return list of matched creators
     */
    List<SubsetCreator> 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(Subset subset);

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

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

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

	/**
	 * Generate Excel file with MCPD passport data for provided subset.
	 *
	 * @param subset the subset
	 * @param outputStream the stream
	 */
	void writeXlsxMCPD(Subset 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 Subset source);

	public static class SubsetSuggestionPage {
		@JsonUnwrapped
		public FilteredPage<Subset, SubsetFilter> page;
		public Map<String, ElasticsearchService.TermResult> suggestions;

		public static SubsetSuggestionPage from(FilteredPage<Subset, SubsetFilter> page, Map<String, ElasticsearchService.TermResult> suggestions) {
			SubsetSuggestionPage res = new SubsetSuggestionPage();
			res.page = page;
			res.suggestions = suggestions;

			return res;
		}
	}

	public static class SubsetOverview {
		public String filterCode;
		public SubsetFilter filter;
		public long subsetCount;
		public Map<String, TermResult> overview;
		public Map<String, TermResult> suggestions;

		public static SubsetOverview from(String filterCode, SubsetFilter filter, Map<String, TermResult> overview, long subsetCount, Map<String, TermResult> suggestions) {
			SubsetOverview res = new SubsetOverview();
			res.filterCode = filterCode;
			res.filter = filter;
			res.overview = overview;
			res.subsetCount = subsetCount;
			res.suggestions = suggestions;

			return res;
		}
	}


	/**
	 * 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(FaoInstitute currentInstitute, FaoInstitute newInstitute);
}