Commit b0e99e4b authored by Matija Obreza's avatar Matija Obreza
Browse files

Add REST API support for RequestService

parent a2675a6b
......@@ -17,6 +17,7 @@
package org.genesys2.server.model.genesys;
import java.text.MessageFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
......@@ -26,6 +27,8 @@ import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang.math.RandomUtils;
import org.genesys2.server.model.VersionedAuditedModel;
......@@ -60,6 +63,9 @@ public class MaterialRequest extends VersionedAuditedModel {
@OneToMany(cascade={}, mappedBy="sourceRequest")
private List<MaterialSubRequest> subRequests;
@Temporal(TemporalType.TIMESTAMP)
private Date lastReminderDate;
@PrePersist
void prepersist() {
if (this.uuid == null)
......@@ -129,4 +135,12 @@ public class MaterialRequest extends VersionedAuditedModel {
public void setSubRequests(List<MaterialSubRequest> subRequests) {
this.subRequests = subRequests;
}
public Date getLastReminderDate() {
return lastReminderDate;
}
public void setLastReminderDate(Date lastReminderDate) {
this.lastReminderDate = lastReminderDate;
}
}
......@@ -17,6 +17,7 @@
package org.genesys2.server.model.genesys;
import java.text.MessageFormat;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
......@@ -25,6 +26,8 @@ import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.commons.lang.math.RandomUtils;
import org.genesys2.server.model.VersionedAuditedModel;
......@@ -65,6 +68,9 @@ public class MaterialSubRequest extends VersionedAuditedModel {
@ManyToOne(cascade = {}, optional = false)
private MaterialRequest sourceRequest;
@Temporal(TemporalType.TIMESTAMP)
private Date lastReminderDate;
@PrePersist
void prepersist() {
if (this.uuid == null)
......@@ -124,6 +130,14 @@ public class MaterialSubRequest extends VersionedAuditedModel {
this.sourceRequest = sourceRequest;
}
public Date getLastReminderDate() {
return lastReminderDate;
}
public void setLastReminderDate(Date lastReminderDate) {
this.lastReminderDate = lastReminderDate;
}
@Override
public String toString() {
return MessageFormat.format("SubRequest uuid={0} inst={1} body={2}", uuid, instCode, body);
......
......@@ -63,7 +63,7 @@ public class GenesysJsonFactory {
private static int[] toIntArray(String arrString) {
if (StringUtils.isBlank(arrString))
return null;
String[] split = arrString.trim().split(";");
String[] split = arrString.trim().split("[;,]");
int[] intArr = new int[split.length];
for (int i = 0; i < split.length; i++) {
// TODO Could throw NFE
......
......@@ -16,6 +16,9 @@
package org.genesys2.server.persistence.domain;
import java.util.List;
import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
......@@ -29,4 +32,6 @@ public interface MaterialSubRequestRepository extends JpaRepository<MaterialSubR
MaterialSubRequest findByInstCodeAndUuid(String instCode, String uuid);
List<MaterialSubRequest> findBySourceRequest(MaterialRequest sourceRequest);
}
......@@ -28,19 +28,41 @@ import org.springframework.data.domain.Pageable;
public interface RequestService {
MaterialRequest sendRequest(RequestInfo requestInfo, Set<Long> accessionIds) throws RequestException;
MaterialRequest createRequest(RequestInfo requestInfo, EasySMTA.EasySMTAUserData pid, Set<Long> accessionIds) throws RequestException;
MaterialRequest getRequest(String uuid);
/**
* Creates a {@link MaterialRequest} and sends a validation email to user
*
* @param requestInfo
* @param accessionIds
* @return
* @throws RequestException
*/
MaterialRequest initiateRequest(RequestInfo requestInfo, Set<Long> accessionIds) 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
*/
MaterialRequest validateClientRequest(String tokenUuid, String key) throws RequestException, NoSuchVerificationTokenException;
/**
* Relay sub-request to holding institute
*
* @param materialSubRequest
*/
void relayRequest(MaterialSubRequest materialSubRequest);
/**
* Attempt to validate receipt of subrequest
*/
MaterialSubRequest validateReceipt(String tokenUuid, String key) throws NoSuchVerificationTokenException;
static class RequestException extends Exception {
public RequestException(String message) {
super(message);
......@@ -50,7 +72,7 @@ public interface RequestService {
super(message, e);
}
}
static class NoPidException extends RuntimeException {
public NoPidException(String message) {
super(message);
......@@ -104,5 +126,23 @@ public interface RequestService {
MaterialSubRequest get(FaoInstitute institute, String uuid);
MaterialRequest sendValidationEmail(MaterialRequest materialRequest);
/**
* Recheck Easy-SMTA for PID
*
* @param materialRequest
* @throws NoPidException
* @return
*/
MaterialRequest recheckPid(MaterialRequest materialRequest);
/**
* Allow admin to validate request (recheck PID, relay)
*
* @param materialRequest
* @return
*/
MaterialRequest validateRequest(MaterialRequest materialRequest);
}
......@@ -18,6 +18,7 @@ package org.genesys2.server.service.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
......@@ -100,7 +101,7 @@ public class RequestServiceImpl implements RequestService {
@Override
@Transactional
public MaterialRequest sendRequest(RequestInfo requestInfo, Set<Long> accessionIds) throws RequestException {
public MaterialRequest initiateRequest(RequestInfo requestInfo, Set<Long> accessionIds) throws RequestException {
Set<Long> availableAccessionIds = genesysService.filterAvailable(accessionIds);
Locale locale = LocaleContextHolder.getLocale();
System.err.println("Current locale: " + locale);
......@@ -111,42 +112,56 @@ public class RequestServiceImpl implements RequestService {
// Check Easy-SMTA for PID
EasySMTA.EasySMTAUserData pid = pidChecker.getUserData(requestInfo.getEmail());
MaterialRequest request = createRequest(requestInfo, pid, availableAccessionIds);
return sendValidationEmail(request);
}
// Send email to the user with verification
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
public MaterialRequest sendValidationEmail(MaterialRequest materialRequest) {
RequestBody rb = null;
try {
rb = mapper.readValue(materialRequest.getBody(), RequestBody.class);
} catch (IOException e) {
// FIXME Some other exception?
throw new RuntimeException("Could not handle request JSON", e);
}
Article article;
if (pid == null) {
if (StringUtils.isBlank(materialRequest.getPid())) {
LOG.warn("No such user in ITPGRFA system");
article = contentService.getGlobalArticle("smtp.material-confirm-no-pid", Locale.ENGLISH);
} else {
article = contentService.getGlobalArticle("smtp.material-confirm", Locale.ENGLISH);
}
MaterialRequest request = createRequest(requestInfo, pid, availableAccessionIds);
// Generate verification token+key
VerificationToken verificationToken = tokenVerificationService.generateToken(REQUEST_TOKENTYPE, request.getUuid());
VerificationToken verificationToken = tokenVerificationService.generateToken(REQUEST_TOKENTYPE, materialRequest.getUuid());
// Send email to the user with verification
Page<Accession> accessions = genesysService.listAccessions(availableAccessionIds, new PageRequest(0, Integer.MAX_VALUE));
Page<Accession> accessions = genesysService.listAccessions(rb.accessionIds, new PageRequest(0, Integer.MAX_VALUE));
// Create the root hash
Map<String, Object> root = new HashMap<String, Object>();
root.put("baseUrl", baseUrl);
root.put("verificationToken", verificationToken);
root.put("pid", pid);
root.put("pid", rb.pid);
root.put("accessions", accessions.getContent());
String mailBody = contentService.processTemplate(article.getBody(), root);
String mailSubject = "[" + request.getUuid() + "] " + article.getTitle();
String mailSubject = "[" + materialRequest.getUuid() + "] " + article.getTitle();
LOG.info(">>>" + mailBody);
// send to user
emailService.sendMail(mailSubject, mailBody, request.getEmail());
emailService.sendMail(mailSubject, mailBody, materialRequest.getEmail());
return request;
materialRequest.setLastReminderDate(new Date());
return requestRepository.save(materialRequest);
}
@Override
@Transactional(readOnly = false)
public MaterialRequest createRequest(RequestInfo requestInfo, EasySMTA.EasySMTAUserData pid, Set<Long> accessionIds) throws RequestException {
MaterialRequest createRequest(RequestInfo requestInfo, EasySMTA.EasySMTAUserData pid, Set<Long> accessionIds) throws RequestException {
Set<Long> availableAccessionIds = genesysService.filterAvailable(accessionIds);
if (availableAccessionIds == null || availableAccessionIds.size() == 0) {
......@@ -185,10 +200,42 @@ public class RequestServiceImpl implements RequestService {
VerificationToken consumedToken = tokenVerificationService.consumeToken(REQUEST_TOKENTYPE, tokenUuid, key);
MaterialRequest materialRequest = requestRepository.findByUuid(consumedToken.getData());
// Client email is confirmed
materialRequest.setState(MaterialRequest.VALIDATED);
validateRequest(materialRequest);
if (StringUtils.isNotBlank(materialRequest.getPid())) {
// If PID is registered, break the request up
breakup(materialRequest);
relayRequests(materialRequest);
return materialRequest;
} else {
// Notify user
throw new NoPidException("Not registered with PID server");
}
}
@Transactional
private void relayRequests(MaterialRequest materialRequest) {
List<MaterialSubRequest> subRequests = subRequestRepository.findBySourceRequest(materialRequest);
if (subRequests.size() == 0) {
LOG.info("Nothing to relay.");
return;
}
LOG.info("Material subrequests " + subRequests.size());
materialRequest.setState(MaterialRequest.DISPATCHED);
requestRepository.save(materialRequest);
for (MaterialSubRequest msr : subRequests) {
relayRequest(msr);
}
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
public MaterialRequest recheckPid(MaterialRequest materialRequest) {
if (StringUtils.isBlank(materialRequest.getPid())) {
// re-test email for PID
EasySMTA.EasySMTAUserData pid = pidChecker.getUserData(materialRequest.getEmail());
......@@ -201,32 +248,59 @@ public class RequestServiceImpl implements RequestService {
RequestBody rb = mapper.readValue(materialRequest.getBody(), RequestBody.class);
rb.pid = pid;
materialRequest.setBody(serialize(rb));
requestRepository.save(materialRequest);
return requestRepository.save(materialRequest);
} catch (IOException e) {
// FIXME Some other exception?
throw new RuntimeException("Could not handle request JSON", e);
}
} else {
return materialRequest;
}
}
if (StringUtils.isNotBlank(materialRequest.getPid())) {
// If PID is registered, break the request up
List<MaterialSubRequest> subRequests = breakup(materialRequest);
LOG.info("Generated subrequests " + subRequests.size());
materialRequest.setState(MaterialRequest.DISPATCHED);
requestRepository.save(materialRequest);
/**
* Mark request as validated if PID checks out.
*
* @param materialRequest
* @return
*/
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
public MaterialRequest validateRequest(MaterialRequest materialRequest) {
// Client email is confirmed
materialRequest.setState(MaterialRequest.VALIDATED);
materialRequest = requestRepository.save(materialRequest);
for (MaterialSubRequest msr : subRequests) {
relayRequest(msr);
}
recheckPid(materialRequest);
return materialRequest;
} else {
// Notify user
throw new NoPidException("Not registered with PID server");
}
breakup(materialRequest);
relayRequests(materialRequest);
return materialRequest;
}
/**
* Create requests to holding institutes if no subrequests exist for this
* request
*
* @param materialRequest
* @return
*/
private List<MaterialSubRequest> breakup(MaterialRequest materialRequest) {
if (StringUtils.isBlank(materialRequest.getPid())) {
LOG.warn("Material request has no PID, will not break it up.");
throw new NoPidException("Not breaking up request without PID.");
}
List<MaterialSubRequest> existingRequests = subRequestRepository.findBySourceRequest(materialRequest);
if (existingRequests.size() > 0) {
// check for subrequests
LOG.warn("Subrequests exists, will not recreate them.");
return existingRequests;
}
RequestBody rb = null;
try {
rb = mapper.readValue(materialRequest.getBody(), RequestBody.class);
......@@ -260,7 +334,7 @@ public class RequestServiceImpl implements RequestService {
}
/**
* Take original request and generate sub-requests to individual institutes
* Relay sub-request to holding institute
*/
@Override
@Transactional
......@@ -316,6 +390,9 @@ public class RequestServiceImpl implements RequestService {
// send to recipient
emailService.sendMail(mailSubject, mailBody, emailCc, materialSubRequest.getInstEmail());
materialSubRequest.setLastReminderDate(new Date());
subRequestRepository.save(materialSubRequest);
}
@Override
......@@ -343,11 +420,6 @@ public class RequestServiceImpl implements RequestService {
}
}
@Override
public MaterialRequest getRequest(String uuid) {
return requestRepository.findByUuid(uuid);
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR')")
public Page<MaterialRequest> list(Pageable pageable) {
......
......@@ -140,7 +140,7 @@ public class RequestController extends BaseController {
try {
// send email to registered email address, wait for
// response
requestService.sendRequest(requestInfo, selectionBean.copy());
requestService.initiateRequest(requestInfo, selectionBean.copy());
} catch (RequestException e) {
_logger.warn(e.getMessage());
return start(model);
......
......@@ -68,12 +68,38 @@ public class RequestsController extends RestController {
*/
@RequestMapping(value = "/requests/r/{uuid:.{36}}", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
Object getRequest(@PathVariable("uuid") String uuid) {
MaterialRequest getRequest(@PathVariable("uuid") String uuid) {
LOG.info("Loading request uuid=" + uuid);
MaterialRequest request = requestService.get(uuid);
return request;
}
/**
* Validate request
*
* @return
*/
@RequestMapping(value = "/requests/r/{uuid:.{36}}/reconfirm", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
MaterialRequest reconfirmRequest(@PathVariable("uuid") String uuid) {
LOG.info("Loading request uuid=" + uuid);
MaterialRequest materialRequest = requestService.get(uuid);
return requestService.sendValidationEmail(materialRequest);
}
/**
* Validate request
*
* @return
*/
@RequestMapping(value = "/requests/r/{uuid:.{36}}/validate", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
MaterialRequest validateRequest(@PathVariable("uuid") String uuid) {
LOG.info("Loading request uuid=" + uuid);
MaterialRequest materialRequest = requestService.get(uuid);
return requestService.validateRequest(materialRequest);
}
/**
* List institute requests
*
......
......@@ -43,6 +43,7 @@ public class MaterialRequestSerializer extends JsonSerializer<MaterialRequest> {
jgen.writeObjectField("state", request.getState());
jgen.writeObjectField("createdDate", request.getCreatedDate());
jgen.writeObjectField("lastModifiedDate", request.getLastModifiedDate());
jgen.writeObjectField("lastReminderDate", request.getLastReminderDate());
try {
List<MaterialSubRequest> list;
......
......@@ -41,6 +41,7 @@ public class MaterialSubRequestSerializer extends JsonSerializer<MaterialSubRequ
jgen.writeObjectField("state", request.getState());
jgen.writeObjectField("createdDate", request.getCreatedDate());
jgen.writeObjectField("lastModifiedDate", request.getLastModifiedDate());
jgen.writeObjectField("lastReminderDate", request.getLastReminderDate());
if (StringUtils.isNotBlank(request.getBody())) {
jgen.writeRaw(",\"body\":");
......
......@@ -1869,4 +1869,8 @@ html[dir="rtl"] ul.statistics .stats-number {
.no-close .ui-dialog-titlebar-close {
display: none;
}
.ui-autocomplete.ui-widget {
z-index: 100;
}
\ No newline at end of file
......@@ -159,13 +159,12 @@ public class MaterialRequestTest {
@Test
public void testCreateRequest() {
RequestInfo requestInfo = new RequestInfo();
EasySMTA.EasySMTAUserData pid = generatePid();
Set<Long> accessionIds = generateAccessionIds();
MaterialRequest request = null;
try {
request = requestService.createRequest(requestInfo, pid, accessionIds);
request = requestService.initiateRequest(requestInfo, accessionIds);
} catch (RequestException e) {
fail(e.getMessage());
}
......@@ -177,7 +176,7 @@ public class MaterialRequestTest {
assertTrue(request.getPid().equals("pid1"));
assertTrue(request.getEmail().equals("email@localhost"));
MaterialRequest loaded = requestService.getRequest(request.getUuid());
MaterialRequest loaded = requestService.get(request.getUuid());
assertTrue("Could not load request", loaded != null);
assertTrue("Got something else back", loaded.getId().equals(request.getId()));
}
......@@ -216,12 +215,12 @@ public class MaterialRequestTest {
RequestInfo requestInfo = new RequestInfo();
Set<Long> accessionIds = generateAccessionIds();
requestService.sendRequest(requestInfo, accessionIds);
requestService.initiateRequest(requestInfo, accessionIds);
}
@Test
public void loadNonExistent() {
MaterialRequest loaded = requestService.getRequest("non-existent-uuid");
MaterialRequest loaded = requestService.get("non-existent-uuid");
assertTrue("Should be null", loaded == null);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment