Commit a47c4042 authored by Matija Obreza's avatar Matija Obreza

FIX #11 Improved material request handling

parent 2eb4c341
...@@ -98,18 +98,18 @@ ...@@ -98,18 +98,18 @@
<name>Releases</name> <name>Releases</name>
<url>https://oss.sonatype.org/content/repositories/releases</url> <url>https://oss.sonatype.org/content/repositories/releases</url>
</repository> </repository>
<repository> <repository>
<id>sonatype mirror</id> <id>sonatype mirror</id>
<url>http://search.maven.org/remotecontent?filepath=</url> <url>http://search.maven.org/remotecontent?filepath=</url>
</repository> </repository>
</repositories> </repositories>
<pluginRepositories> <pluginRepositories>
<pluginRepository> <pluginRepository>
<id>sonatype mirror</id> <id>sonatype mirror</id>
<url>http://search.maven.org/remotecontent?filepath=</url> <url>http://search.maven.org/remotecontent?filepath=</url>
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
<dependencies> <dependencies>
<!--Test dependencies --> <!--Test dependencies -->
...@@ -479,14 +479,14 @@ ...@@ -479,14 +479,14 @@
<artifactId>hazelcast-hibernate4</artifactId> <artifactId>hazelcast-hibernate4</artifactId>
<version>3.1.5</version> <version>3.1.5</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.jena</groupId> <groupId>org.apache.jena</groupId>
<artifactId>apache-jena-libs</artifactId> <artifactId>apache-jena-libs</artifactId>
<type>pom</type> <type>pom</type>
<version>2.10.1</version> <version>2.10.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.bioversityinternational</groupId> <groupId>org.bioversityinternational</groupId>
<artifactId>org.bioversityinternational.ontology</artifactId> <artifactId>org.bioversityinternational.ontology</artifactId>
...@@ -544,7 +544,7 @@ ...@@ -544,7 +544,7 @@
<plugin> <plugin>
<inherited>true</inherited> <inherited>true</inherited>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version> <version>3.1</version>
<configuration> <configuration>
<source>${jdk.source}</source> <source>${jdk.source}</source>
<target>${jdk.target}</target> <target>${jdk.target}</target>
...@@ -553,6 +553,16 @@ ...@@ -553,6 +553,16 @@
<showWarnings>true</showWarnings> <showWarnings>true</showWarnings>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<forkMode>once</forkMode>
<argLine>-Xms512m -Xmx1024m</argLine>
<testFailureIgnore>false</testFailureIgnore>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
......
...@@ -31,8 +31,14 @@ import org.genesys2.server.model.VersionedAuditedModel; ...@@ -31,8 +31,14 @@ import org.genesys2.server.model.VersionedAuditedModel;
@Entity @Entity
@Table(name = "request") @Table(name = "request")
public class MaterialRequest extends VersionedAuditedModel { public class MaterialRequest extends VersionedAuditedModel {
public static final int NOTVALIDATED = 0;
public static final int VALIDATED = 1;
public static final int DISPATCHED = 2;
@Column(length = 36, unique=true) @Column
private int state = NOTVALIDATED;
@Column(length = 36, unique = true)
private String uuid; private String uuid;
@Column(length = 200, nullable = false) @Column(length = 200, nullable = false)
...@@ -42,7 +48,7 @@ public class MaterialRequest extends VersionedAuditedModel { ...@@ -42,7 +48,7 @@ public class MaterialRequest extends VersionedAuditedModel {
@Lob @Lob
private String body; private String body;
@Column(length = 32, nullable = false) @Column(length = 32, nullable = true)
private String pid; private String pid;
@PrePersist @PrePersist
...@@ -55,6 +61,14 @@ public class MaterialRequest extends VersionedAuditedModel { ...@@ -55,6 +61,14 @@ public class MaterialRequest extends VersionedAuditedModel {
public MaterialRequest() { public MaterialRequest() {
} }
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getUuid() { public String getUuid() {
return uuid; return uuid;
} }
...@@ -85,7 +99,8 @@ public class MaterialRequest extends VersionedAuditedModel { ...@@ -85,7 +99,8 @@ public class MaterialRequest extends VersionedAuditedModel {
} }
/** /**
* @param pid EasySMTA PID * @param pid
* EasySMTA PID
*/ */
public void setPid(String pid) { public void setPid(String pid) {
this.pid = pid; this.pid = pid;
......
/**
* 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.genesys2.server.model.genesys;
import java.text.MessageFormat;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import org.apache.commons.lang.math.RandomUtils;
import org.genesys2.server.model.VersionedAuditedModel;
/**
* {@link MaterialRequest} is broken down into individual requests to
* institutes.
*
* @author matijaobreza
*
*/
@Entity
@Table(name = "requestsub")
public class MaterialSubRequest extends VersionedAuditedModel {
public static final int NOTCONFIRMED = 0;
public static final int CONFIRMED = 1;
@Column
private int state = NOTCONFIRMED;
@Column(length = 36, unique = true)
private String uuid;
@Column(length = 8, nullable = false)
private String instCode;
@Column(length = 200, nullable = true)
private String instEmail;
@Column(length = 100000)
@Lob
private String body;
@ManyToOne(cascade = {}, optional = false)
private MaterialRequest sourceRequest;
@PrePersist
void prepersist() {
if (this.uuid == null)
this.uuid = UUID.nameUUIDFromBytes(
("genesys:request:" + sourceRequest.getUuid() + ":" + instCode + ":" + System.currentTimeMillis() + ":" + RandomUtils.nextInt(100))
.getBytes()).toString();
}
public MaterialSubRequest() {
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getInstCode() {
return instCode;
}
public void setInstCode(String instCode) {
this.instCode = instCode;
}
public String getInstEmail() {
return instEmail;
}
public void setInstEmail(String instEmail) {
this.instEmail = instEmail;
}
public MaterialRequest getSourceRequest() {
return sourceRequest;
}
public void setSourceRequest(MaterialRequest sourceRequest) {
this.sourceRequest = sourceRequest;
}
@Override
public String toString() {
return MessageFormat.format("SubRequest uuid={0} inst={1} body={2}", uuid, instCode, body);
}
}
...@@ -107,6 +107,10 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> { ...@@ -107,6 +107,10 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> {
@Query("select count(a.id) from Accession a where a.id in ( ?1 ) and a.availability = true") @Query("select count(a.id) from Accession a where a.id in ( ?1 ) and a.availability = true")
long countAvailable(Set<Long> accessionIds); long countAvailable(Set<Long> accessionIds);
@Query("select a.id from Accession a where a.id in ( ?1 ) and a.availability = true")
Set<Long> filterAvailable(Set<Long> accessionIds);
@Modifying @Modifying
@Query("update Accession a set a.inSvalbard = true where a in ?1") @Query("update Accession a set a.inSvalbard = true where a in ?1")
...@@ -114,4 +118,10 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> { ...@@ -114,4 +118,10 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> {
Page<Accession> findByInstituteAndTaxSpecies(FaoInstitute institute, long taxSpecies, Pageable pageable); Page<Accession> findByInstituteAndTaxSpecies(FaoInstitute institute, long taxSpecies, Pageable pageable);
@Query("select distinct a.institute from Accession a where a.id in ( ?1 )")
List<FaoInstitute> findDistinctInstitutesFor(Set<Long> accessionIds);
@Query("select distinct a.id from Accession a where a.institute = ?1 and a.id in ( ?2 )")
Set<Long> findByInstituteAndIds(FaoInstitute institute, Set<Long> accessionIds);
} }
/**
* 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.genesys2.server.persistence.domain;
import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MaterialSubRequestRepository extends JpaRepository<MaterialSubRequest, Long> {
MaterialSubRequest findByUuid(String uuid);
}
...@@ -123,7 +123,8 @@ public interface GenesysService { ...@@ -123,7 +123,8 @@ public interface GenesysService {
void saveSvalbards(List<SvalbardData> svalbards); void saveSvalbards(List<SvalbardData> svalbards);
long countAvailable(Set<Long> accessionIds); long countAvailable(Set<Long> accessionIds);
Set<Long> filterAvailable(Set<Long> accessionIds);
void saveAccession(Accession... accession); void saveAccession(Accession... accession);
void updateAccessionCount(FaoInstitute institute); void updateAccessionCount(FaoInstitute institute);
...@@ -171,4 +172,8 @@ public interface GenesysService { ...@@ -171,4 +172,8 @@ public interface GenesysService {
*/ */
Accession getAccession(String instCode, String acceNumb); Accession getAccession(String instCode, String acceNumb);
List<FaoInstitute> findHoldingInstitutes(Set<Long> accessionIds);
Set<Long> listAccessions(FaoInstitute holdingInstitute, Set<Long> accessionIds);
} }
...@@ -16,17 +16,81 @@ ...@@ -16,17 +16,81 @@
package org.genesys2.server.service; package org.genesys2.server.service;
import java.io.IOException;
import java.util.Set; import java.util.Set;
import org.genesys2.server.model.genesys.MaterialRequest; import org.genesys2.server.model.genesys.MaterialRequest;
import org.genesys2.server.service.impl.EasySMTAConnector.EasySMTAUserData; import org.genesys2.server.model.genesys.MaterialSubRequest;
import org.genesys2.server.service.TokenVerificationService.NoSuchVerificationTokenException;
public interface RequestService { public interface RequestService {
MaterialRequest sendRequest(EasySMTAUserData pid, Set<Long> accessionIds); MaterialRequest sendRequest(RequestInfo requestInfo, Set<Long> accessionIds) throws RequestException;
MaterialRequest createRequest(EasySMTAUserData pid, Set<Long> accessionIds); MaterialRequest createRequest(RequestInfo requestInfo, EasySMTA.EasySMTAUserData pid, Set<Long> accessionIds) throws RequestException;
MaterialRequest getRequest(String uuid); MaterialRequest getRequest(String uuid);
MaterialRequest validateClientRequest(String tokenUuid, String key) throws RequestException, NoSuchVerificationTokenException;
void relayRequest(MaterialSubRequest materialSubRequest);
MaterialSubRequest validateReceipt(String tokenUuid, String key) throws NoSuchVerificationTokenException;
static class RequestException extends Exception {
public RequestException(String message) {
super(message);
}
public RequestException(String message, IOException e) {
super(message, e);
}
}
static class NoPidException extends RuntimeException {
public NoPidException(String message) {
super(message);
}
}
public static class RequestInfo {
private String email;
private int purposeType;
private boolean preacceptSMTA;
private String notes;
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;
}
}
} }
...@@ -24,6 +24,7 @@ import java.sql.ResultSet; ...@@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
...@@ -197,6 +198,16 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset ...@@ -197,6 +198,16 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return accessionRepository.findByInstitute(faoInstitute, pageable); return accessionRepository.findByInstitute(faoInstitute, pageable);
} }
@Override
public List<FaoInstitute> findHoldingInstitutes(Set<Long> accessionIds) {
return accessionRepository.findDistinctInstitutesFor(accessionIds);
}
@Override
public Set<Long> listAccessions(FaoInstitute institute, Set<Long> accessionIds) {
return accessionRepository.findByInstituteAndIds(institute, accessionIds);
}
@Override @Override
public Page<Accession> listAccessions(Collection<Long> accessionIds, Pageable pageable) { public Page<Accession> listAccessions(Collection<Long> accessionIds, Pageable pageable) {
if (accessionIds == null || accessionIds.size() == 0) { if (accessionIds == null || accessionIds.size() == 0) {
...@@ -579,6 +590,13 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset ...@@ -579,6 +590,13 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return 0; return 0;
return accessionRepository.countAvailable(accessionIds); return accessionRepository.countAvailable(accessionIds);
} }
@Override
public Set<Long> filterAvailable(Set<Long> accessionIds) {
if (accessionIds == null || accessionIds.size() == 0)
return Collections.emptySet();
return accessionRepository.filterAvailable(accessionIds);
}
/** /**
* Returns datasets to which current user has 'WRITE' * Returns datasets to which current user has 'WRITE'
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.genesys2.server.servlet.controller; package org.genesys2.server.servlet.controller;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -23,8 +25,9 @@ import org.genesys2.server.model.impl.User; ...@@ -23,8 +25,9 @@ import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.ContentService; import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.RequestService; import org.genesys2.server.service.RequestService;
import org.genesys2.server.service.impl.EasySMTAConnector; import org.genesys2.server.service.RequestService.RequestException;
import org.genesys2.server.service.impl.EasySMTAConnector.EasySMTAUserData; import org.genesys2.server.service.RequestService.RequestInfo;
import org.genesys2.server.service.TokenVerificationService.NoSuchVerificationTokenException;
import org.genesys2.spring.SecurityContextUtil; import org.genesys2.spring.SecurityContextUtil;
import org.genesys2.util.ReCaptchaUtil; import org.genesys2.util.ReCaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -34,6 +37,7 @@ import org.springframework.data.domain.PageRequest; ...@@ -34,6 +37,7 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
...@@ -57,9 +61,6 @@ public class RequestController extends BaseController { ...@@ -57,9 +61,6 @@ public class RequestController extends BaseController {
@Autowired @Autowired
private ContentService contentService; private ContentService contentService;
@Autowired
private EasySMTAConnector pidChecker;
@Value("${captcha.privateKey}") @Value("${captcha.privateKey}")
private String captchaPrivateKey; private String captchaPrivateKey;
...@@ -91,20 +92,26 @@ public class RequestController extends BaseController { ...@@ -91,20 +92,26 @@ public class RequestController extends BaseController {
User currentUser = SecurityContextUtil.getCurrentUser(); User currentUser = SecurityContextUtil.getCurrentUser();
model.addAttribute("blurp", contentService.getGlobalArticle("request-personal", getLocale())); model.addAttribute("blurp", contentService.getGlobalArticle("request-personal", getLocale()));
model.addAttribute("captchaPublicKey", captchaPublicKey); model.addAttribute("captchaPublicKey", captchaPublicKey);
if (currentUser != null) if (!model.containsAttribute("requestEmail") && currentUser != null)
model.addAttribute("requestEmail", currentUser.getEmail()); model.addAttribute("requestEmail", currentUser.getEmail());
return "/request/personal"; return "/request/personal";
} }
@RequestMapping(method = RequestMethod.POST, value = "/submit") @RequestMapping(method = RequestMethod.POST, value = "/submit")
public String submit(ModelMap model, HttpServletRequest req, @RequestParam(value = "email", defaultValue = "", required = true) String emailAddress, public String submit(ModelMap model, HttpServletRequest req, @RequestParam(value = "email", defaultValue = "", required = true) String requestEmail,
@RequestParam(value = "recaptcha_challenge_field", required = false) String challenge, @RequestParam(value = "recaptcha_challenge_field", required = false) String challenge,
@RequestParam(value = "recaptcha_response_field", required = false) String response) { @RequestParam(value = "recaptcha_response_field", required = false) String response, @RequestParam(value = "notes") String notes,
emailAddress = emailAddress.trim(); @RequestParam(value = "purpose") int purposeType, @RequestParam(value = "smta", required = false) Boolean preacceptSMTA) {
User currentUser = SecurityContextUtil.getCurrentUser();
if (StringUtils.isBlank(emailAddress)) { User currentUser = SecurityContextUtil.getCurrentUser();
_logger.warn("No email address was specified for request. Stopping here."); model.addAttribute("notes", notes);
model.addAttribute("requestEmail", requestEmail);
InternetAddress internetAddress;
try {
internetAddress = new InternetAddress(requestEmail, true);