RequestService.java

/**
 * Copyright 2014 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.util.List;
import java.util.Set;
import java.util.UUID;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.genesys.server.model.genesys.MaterialRequest;
import org.genesys.server.model.genesys.MaterialSubRequest;
import org.genesys.server.model.impl.FaoInstitute;
import org.genesys.server.service.TokenVerificationService.NoSuchVerificationTokenException;
import org.genesys.server.service.filter.MaterialRequestFilter;
import org.genesys.server.service.filter.MaterialSubRequestFilter;
import org.genesys.server.exception.EasySMTAException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import com.fasterxml.jackson.annotation.JsonProperty;

import lombok.Data;

public interface RequestService {

	/**
	 * Creates a {@link MaterialRequest} and sends a validation email to user
	 * 
	 * @param requestInfo
	 * @param accessionIds
	 * @return
	 * @throws RequestException
	 */
	MaterialRequest initiateRequest(@Valid RequestInfo requestInfo, Set<Long> accessionIds, String origin, String sid, String lang) throws RequestException;

	/**
	 * Creates a {@link MaterialRequest} and sends a validation email to user
	 *
	 * @param requestInfo
	 * @param accessionUuids
	 * @param origin
	 * @param sid
	 * @param lang
	 * @return
	 * @throws RequestException
	 */
	MaterialRequest initiateRequestByUuids(@Valid RequestInfo requestInfo, Set<UUID> accessionUuids, String origin, String sid, String lang) throws RequestException;


	/**
	 * Create a new DRAFT request for material with DRAFT sub requests by accession ids.
	 *
	 * @param accessionIds set of accession ids
	 * @return DRAFT materialRequest
	 */
	MaterialRequest createDraftRequest(Set<Long> accessionIds) throws RequestException;

	/**
	 * Process request
	 * Fill request and sub requests with request info and send validation email.
	 *
	 * @param requestInfo request info
	 * @param requestId material request id
	 * @return processed materialRequest
	 */
	MaterialRequest processRequest(@Valid RequestInfo requestInfo, Long requestId) throws RequestException;

	/**
	 * Validation request attempt by user
	 * 
	 * @param tokenUuid
	 * @param key
	 * @return
	 * @throws RequestException
	 *             On request processing exception (e.g. missing PID data)
	 * @throws NoSuchVerificationTokenException
	 *             If verification token is invalid
	 * @throws NoPidException 
	 * @throws EasySMTAException 
	 */
	MaterialRequest validateClientRequest(String tokenUuid, String key) throws RequestException, NoSuchVerificationTokenException, NoPidException, EasySMTAException, TokenVerificationService.TokenExpiredException;

	/**
	 * Relay sub-request to holding institute
	 * 
	 * @param materialSubRequest
	 * @return updated materialSubRequest
	 */
	MaterialSubRequest relayRequest(MaterialSubRequest materialSubRequest);

	/**
	 * Attempt to validate receipt of subrequest
	 */
	MaterialSubRequest validateReceipt(String tokenUuid, String key) throws NoSuchVerificationTokenException, TokenVerificationService.TokenExpiredException;

	MaterialRequest getRequestStatus(UUID uuid);

	Page<MaterialRequest> listMyRequests(MaterialRequestFilter filter, Pageable page);
	
	static class RequestException extends Exception {
		/**
		 *
		 */
		private static final long serialVersionUID = -2916706231454838785L;

		public RequestException(String message) {
			super(message);
		}

		public RequestException(String message, Throwable e) {
			super(message, e);
		}
	}

	static class NoPidException extends Exception {
		/**
		 * 
		 */
		private static final long serialVersionUID = 8218041860499089421L;

		public NoPidException(String message) {
			super(message);
		}
	}

	public static class RequestInfo {
		private String email;
		private int purposeType;
		private boolean preacceptSMTA;
		private String notes;
		@Valid
		private EasySMTA.EasySMTAUserData userData;
		private boolean internalRequest;

		public String getEmail() {
			return email;
		}

		public void setEmail(String email) {
			this.email = email;
		}

		public int getPurposeType() {
			return purposeType;
		}

		public void setPurposeType(int purposeType) {
			this.purposeType = purposeType;
		}

		public boolean isPreacceptSMTA() {
			return preacceptSMTA;
		}

		public void setPreacceptSMTA(boolean preacceptSMTA) {
			this.preacceptSMTA = preacceptSMTA;
		}

		public String getNotes() {
			return notes;
		}

		public void setNotes(String notes) {
			this.notes = notes;
		}

		public EasySMTA.EasySMTAUserData getUserData() {
			return userData;
		}

		public void setUserData(EasySMTA.EasySMTAUserData userData) {
			this.userData = userData;
		}

		public boolean isInternalRequest() {
			return internalRequest;
		}

		public void setInternalRequest(boolean internalRequest) {
			this.internalRequest = internalRequest;
		}
	}

	public static class RequestData {
		@JsonProperty(value = "recaptcha")
		public String captchaResponse;

		public RequestService.RequestInfo requestInfo;

		@JsonProperty(value = "accessions")
		public Set<UUID> accessionUuids;
	}

	@Data
	public static class ProviderInfoRequest {
		@NotNull
		private MaterialSubRequest.State state;
		@Size(min = 1, max = 50)
		private String providerId;
		@Size(min = 1)
		private String providerNote;
	}

	Page<MaterialRequest> list(MaterialRequestFilter filter, Pageable pageable);

	Page<MaterialSubRequest> listSubRequests(MaterialSubRequestFilter filter, Pageable pageable);

	Page<MaterialSubRequest> listMineSubRequests(MaterialSubRequestFilter filter, Pageable pageable);

	Page<MaterialSubRequest> list(FaoInstitute institute, MaterialSubRequestFilter filter, Pageable pageRequest);

	MaterialRequest get(String uuid);

	MaterialRequest get(Long requestId);

	MaterialSubRequest get(FaoInstitute institute, String uuid);

	MaterialSubRequest getSubrequest(String uuid);

	MaterialSubRequest getSubrequest(UUID uuid, Integer version);

	MaterialRequest remove(String uuid);

	MaterialRequest sendValidationEmail(MaterialRequest materialRequest);

	/**
	 * Recheck Easy-SMTA for PID
	 * 
	 * @param materialRequest
	 * @throws NoPidException
	 * @return
	 * @throws EasySMTAException 
	 */
	MaterialRequest recheckPid(MaterialRequest materialRequest) throws NoPidException, EasySMTAException;

	/**
	 * Allow admin to validate request (recheck PID, relay)
	 * 
	 * @param materialRequest
	 * @return
	 * @throws EasySMTAException 
	 * @throws NoPidException 
	 */
	MaterialRequest validateRequest(MaterialRequest materialRequest) throws NoPidException, EasySMTAException;

	/**
	 * Move requests from one institute to its new code
	 * 
	 * @param currentInstitute
	 * @param newInstitute
	 * @return
	 */
	long changeInstitute(FaoInstitute currentInstitute, FaoInstitute newInstitute);

	/**
	 * Set providerId and providerNote
	 *
	 * @param materialSubRequest request
	 * @param faoInstitute institute of request
	 * @param info provider info
	 * @return updated sub request
	 */
	MaterialSubRequest setProviderInfo(MaterialSubRequest materialSubRequest, FaoInstitute faoInstitute, @Valid ProviderInfoRequest info);

	/**
	 * Re-send emails to genebanks for any unconfirmed requests created in the last month, with last reminder sent more than 5 days ago
	 * @return 
	 */
	List<MaterialSubRequest> resendNotConfirmedSubRequests();
}