Commit 65088475 authored by Matija Obreza's avatar Matija Obreza

AccessionId#uuid added, initial resolver code implemented

parent 11ff3298
package org.genesys2.server.model;
import java.util.UUID;
public interface IdUUID {
UUID getUuid();
}
...@@ -5,6 +5,7 @@ import java.util.Date; ...@@ -5,6 +5,7 @@ import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
...@@ -37,7 +38,7 @@ public class AccessionDetails { ...@@ -37,7 +38,7 @@ public class AccessionDetails {
private Long id; private Long id;
@Field(index = FieldIndex.not_analyzed, type = FieldType.String) @Field(index = FieldIndex.not_analyzed, type = FieldType.String)
private String uuid; private UUID uuid;
@Field(type = FieldType.String) @Field(type = FieldType.String)
private String acceNumb; private String acceNumb;
@Field(index = FieldIndex.not_analyzed, type = FieldType.String) @Field(index = FieldIndex.not_analyzed, type = FieldType.String)
...@@ -185,11 +186,11 @@ public class AccessionDetails { ...@@ -185,11 +186,11 @@ public class AccessionDetails {
this.id = id; this.id = id;
} }
public String getUuid() { public UUID getUuid() {
return uuid; return uuid;
} }
public void setUuid(String uuid) { public void setUuid(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
......
...@@ -40,17 +40,6 @@ public abstract class AccessionData extends AccessionId { ...@@ -40,17 +40,6 @@ public abstract class AccessionData extends AccessionId {
public static final List<AccessionData> EMPTY_LIST = Collections.unmodifiableList(new ArrayList<AccessionData>()); public static final List<AccessionData> EMPTY_LIST = Collections.unmodifiableList(new ArrayList<AccessionData>());
@Column(length = 36)
private String uuid;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
@Column(name = "instCode", length = 10, nullable = false) @Column(name = "instCode", length = 10, nullable = false)
private String instituteCode; private String instituteCode;
......
...@@ -16,11 +16,16 @@ ...@@ -16,11 +16,16 @@
package org.genesys2.server.model.genesys; package org.genesys2.server.model.genesys;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Inheritance; import javax.persistence.Inheritance;
import javax.persistence.InheritanceType; import javax.persistence.InheritanceType;
import javax.persistence.PrePersist;
import javax.persistence.Table; import javax.persistence.Table;
import org.genesys2.server.model.IdUUID;
import org.genesys2.server.model.VersionedAuditedModel; import org.genesys2.server.model.VersionedAuditedModel;
/** /**
...@@ -30,6 +35,24 @@ import org.genesys2.server.model.VersionedAuditedModel; ...@@ -30,6 +35,24 @@ import org.genesys2.server.model.VersionedAuditedModel;
@Entity @Entity
@Inheritance(strategy = InheritanceType.JOINED) @Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "acce") @Table(name = "acce")
public class AccessionId extends VersionedAuditedModel { public class AccessionId extends VersionedAuditedModel implements IdUUID {
@Column(columnDefinition = "binary(16)", updatable = false)
protected UUID uuid;
@PrePersist
private void prepersist() {
if (uuid == null) {
uuid = UUID.randomUUID();
}
}
@Override
public UUID getUuid() {
return this.uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
} }
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.genesys2.server.model.json; package org.genesys2.server.model.json;
import java.util.UUID;
import org.genesys2.server.model.json.Api1Constants.Accession; import org.genesys2.server.model.json.Api1Constants.Accession;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
...@@ -39,7 +41,7 @@ public class AccessionJson { ...@@ -39,7 +41,7 @@ public class AccessionJson {
@JsonProperty(value = Accession.SUBTAUTHOR) @JsonProperty(value = Accession.SUBTAUTHOR)
private String subtauthor; private String subtauthor;
@JsonProperty(value = Accession.UUID) @JsonProperty(value = Accession.UUID)
private String uuid; private UUID uuid;
@JsonProperty(value = Accession.ORIGCTY) @JsonProperty(value = Accession.ORIGCTY)
private String orgCty; private String orgCty;
@JsonProperty(value = Accession.ACQDATE) @JsonProperty(value = Accession.ACQDATE)
...@@ -147,11 +149,11 @@ public class AccessionJson { ...@@ -147,11 +149,11 @@ public class AccessionJson {
this.subtauthor = subtauthor; this.subtauthor = subtauthor;
} }
public String getUuid() { public UUID getUuid() {
return uuid; return uuid;
} }
public void setUuid(String uuid) { public void setUuid(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
......
...@@ -16,10 +16,20 @@ ...@@ -16,10 +16,20 @@
package org.genesys2.server.persistence.domain; package org.genesys2.server.persistence.domain;
import java.util.List;
import java.util.UUID;
import org.genesys2.server.model.genesys.AccessionHistoric; import org.genesys2.server.model.genesys.AccessionHistoric;
import org.genesys2.server.model.impl.FaoInstitute;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
public interface AccessionHistoricRepository extends JpaRepository<AccessionHistoric, Long> { public interface AccessionHistoricRepository extends JpaRepository<AccessionHistoric, Long> {
AccessionHistoric findOneByUuid(UUID uuid);
List<AccessionHistoric> findByInstituteAndAccessionName(FaoInstitute faoInstitute, String acceNumb);
List<AccessionHistoric> findByAccessionName(String acceNumb);
} }
...@@ -19,6 +19,7 @@ package org.genesys2.server.persistence.domain; ...@@ -19,6 +19,7 @@ package org.genesys2.server.persistence.domain;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.genesys2.server.model.genesys.Accession; import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Taxonomy2; import org.genesys2.server.model.genesys.Taxonomy2;
...@@ -108,4 +109,8 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> { ...@@ -108,4 +109,8 @@ public interface AccessionRepository extends JpaRepository<Accession, Long> {
@Modifying @Modifying
@Query(nativeQuery=true, value="delete from accession where id = ?1") @Query(nativeQuery=true, value="delete from accession where id = ?1")
public void deleteActive(long id); public void deleteActive(long id);
public Accession findOneByUuid(UUID uuid);
public List<Accession> findByAccessionName(String acceNumb);
} }
package org.genesys2.server.service;
import java.util.List;
import java.util.UUID;
import org.genesys2.server.model.IdUUID;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.impl.FaoInstitute;
public interface ResolverService {
IdUUID forward(UUID uuid);
List<AccessionId> findMatches(FaoInstitute faoInstitute, String acceNumb);
}
...@@ -701,16 +701,9 @@ public class BatchRESTServiceImpl implements BatchRESTService { ...@@ -701,16 +701,9 @@ public class BatchRESTServiceImpl implements BatchRESTService {
private boolean updateUuid(AccessionData accession, JsonNode value) throws RESTApiValueException { private boolean updateUuid(AccessionData accession, JsonNode value) throws RESTApiValueException {
if (value != null) { if (value != null) {
final String uuid = value.isNull() ? null : value.textValue(); final UUID uuid = value.isNull() ? null : UUID.fromString(value.textValue());
if (!StringUtils.equals(uuid, accession.getUuid())) {
if (uuid != null) { if (accession.getUuid() == null && uuid != null) {
try {
// Throws a runtime exception if format is invalid
UUID.fromString(uuid);
} catch (final RuntimeException e) {
throw new RESTApiValueException("UUID " + uuid + " is not in valid format: " + e.getMessage());
}
}
accession.setUuid(uuid); accession.setUuid(uuid);
return true; return true;
} }
......
package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.genesys2.server.model.IdUUID;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionHistoric;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.persistence.domain.AccessionHistoricRepository;
import org.genesys2.server.persistence.domain.AccessionRepository;
import org.genesys2.server.service.ResolverService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class ResolverServiceImpl implements ResolverService {
@Autowired
private AccessionRepository repoAccession;
@Autowired
private AccessionHistoricRepository repoAccessionHistoric;
@Override
public IdUUID forward(UUID uuid) {
Accession accession = repoAccession.findOneByUuid(uuid);
if (accession != null) {
return accession;
}
AccessionHistoric accessionHistoric = repoAccessionHistoric.findOneByUuid(uuid);
if (accessionHistoric != null) {
return accessionHistoric;
}
return null;
}
@Override
public List<AccessionId> findMatches(FaoInstitute faoInstitute, String acceNumb) {
List<AccessionId> matches = new ArrayList<AccessionId>();
if (faoInstitute != null) {
matches.addAll(repoAccession.findByInstituteAndAccessionName(faoInstitute, acceNumb));
matches.addAll(repoAccessionHistoric.findByInstituteAndAccessionName(faoInstitute, acceNumb));
} else {
matches.addAll(repoAccession.findByAccessionName(acceNumb));
matches.addAll(repoAccessionHistoric.findByAccessionName(acceNumb));
}
return matches;
}
}
/**
* Copyright 2015 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.servlet.controller;
import java.util.List;
import java.util.UUID;
import org.genesys2.server.model.IdUUID;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionHistoric;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.ResolverService;
import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping(value = "/resolver")
public class ResolverController {
@Autowired
private ResolverService resolverService;
@Autowired
private InstituteService instituteService;
@RequestMapping(value = "")
public String form() {
return "/resolver/index";
}
@RequestMapping(value = "/reverse", method = RequestMethod.POST, params = { "acceNumb" })
public String reverse(ModelMap model, @RequestParam(required = true, value = "acceNumb") String acceNumb,
@RequestParam(required = false, value = "instCode") String instCode) {
FaoInstitute faoInstitute = instituteService.findInstitute(instCode);
List<AccessionId> accessions = resolverService.findMatches(faoInstitute, acceNumb);
model.addAttribute("accessions", accessions);
return "/resolver/reverse";
}
@RequestMapping(value = "/forward", method = RequestMethod.POST, params = { "uuid" })
public String forwardGui(ModelMap model, @RequestParam(required = true, value = "uuid") UUID uuid) {
return forwardUuid(model, uuid);
}
@RequestMapping(value = "/{uuid:.{36}}", method = RequestMethod.GET)
public String forwardUuid(ModelMap model, @PathVariable(value = "uuid") UUID uuid) {
final IdUUID resolved = resolverService.forward(uuid);
if (resolved == null) {
throw new ResourceNotFoundException();
}
if (resolved instanceof Accession) {
return "redirect:/acn/id/" + ((Accession) resolved).getId();
}
if (resolved instanceof AccessionHistoric) {
return "redirect:/history/acn/id/" + resolved.getUuid();
}
throw new ResourceNotFoundException("We don't have an object with UUID " + uuid);
}
}
...@@ -603,3 +603,13 @@ worldclim.other-climate=Other climatic data ...@@ -603,3 +603,13 @@ worldclim.other-climate=Other climatic data
download.page.title=Before you download download.page.title=Before you download
download.download-now=Start download, I will wait. download.download-now=Start download, I will wait.
resolver.page.index.title=Find permanent identifier
resolver.acceNumb=Accession Number
resolver.instCode=Holding institute code
resolver.lookup=Find identifier
resolver.uuid=UUID
resolver.resolve=Resolve
resolver.page.reverse.title=Resolution results
accession.purl=Permanent URL
...@@ -89,3 +89,8 @@ html[dir="rtl"] { ...@@ -89,3 +89,8 @@ html[dir="rtl"] {
.navbar-right { .navbar-right {
margin-right: 0; margin-right: 0;
} }
.text-clip {
@include text-overflow;
}
...@@ -1254,27 +1254,31 @@ table.accessions tr.not-available>td, table tr.expired>td { ...@@ -1254,27 +1254,31 @@ table.accessions tr.not-available>td, table tr.expired>td {
.crop-details { .crop-details {
font-size: 14px; font-size: 14px;
}
.crop-details>div.row {
background-color: #f8f7f5;
margin: 5px 0 5px 0;
}
.crop-details>div.row>div {
padding: 10px;
}
.crop-details h4 {
color: #2b2924;
font-size: 22px;
font-weight: bold;
margin: 0;
padding: 20px 0 5px;
}
.crop-details h2, .crop-details>div:nth-of-type(even) { > div.row {
background-color: #f3f2ee; background-color: #f8f7f5;
margin: 5px 0 5px 0;
>div {
padding: 10px;
}
}
h4 {
color: #2b2924;
font-size: 22px;
font-weight: bold;
margin: 0;
padding: 20px 0 5px;
}
.header {
font-weight: bold;
}
h2, >div:nth-of-type(even) {
background-color: #f3f2ee;
}
} }
table.crop-details h4 { table.crop-details h4 {
......
...@@ -103,6 +103,16 @@ ...@@ -103,6 +103,16 @@
</div> </div>
<div class="crop-details"> <div class="crop-details">
<c:if test="${accession.uuid ne null}">
<div class="row text-muted">
<div class="col-xs-4"><spring:message code="accession.uuid" /></div>
<div class="col-xs-8"><c:out value="${accession.uuid}" /></div>
</div>
<div class="row">
<div class="col-xs-4"><spring:message code="accession.purl" /></div>
<div class="col-xs-8"><a href="https://purl.org/germplasm/id/${accession.uuid}"><c:out value="https://purl.org/germplasm/id/${accession.uuid}" /></a></div>
</div>
</c:if>
<div class="row"> <div class="row">
<div class="col-xs-4"><spring:message code="accession.holdingInstitute" /></div> <div class="col-xs-4"><spring:message code="accession.holdingInstitute" /></div>
<div class="col-xs-8"><a property="dwc:institutionCode" href="<c:url value="/wiews/${accession.instituteCode}" />"> <c:out value="${accession.institute.fullName}" /> <div class="col-xs-8"><a property="dwc:institutionCode" href="<c:url value="/wiews/${accession.instituteCode}" />"> <c:out value="${accession.institute.fullName}" />
...@@ -116,12 +126,6 @@ ...@@ -116,12 +126,6 @@
<div class="col-xs-4"><spring:message code="accession.accessionName" /></div> <div class="col-xs-4"><spring:message code="accession.accessionName" /></div>
<div class="col-xs-8"><c:out value="${accession.accessionName}" /></div> <div class="col-xs-8"><c:out value="${accession.accessionName}" /></div>
</div> </div>
<c:if test="${accession.uuid ne null}">
<div class="row">
<div class="col-xs-4"><spring:message code="accession.uuid" /></div>
<div class="col-xs-8"><b><c:out value="${accession.uuid}" /></b></div>
</div>
</c:if>
<c:if test="${crops ne null}"> <c:if test="${crops ne null}">
<div class="row"> <div class="row">
......
...@@ -259,7 +259,7 @@ ...@@ -259,7 +259,7 @@
<td class="sel" x-aid="${accession.id}"></td> <td class="sel" x-aid="${accession.id}"></td>
<td><a href="<c:url value="/acn/id/${accession.id}" />"><b><c:out value="${accession.acceNumb}" /></b></a></td> <td><a href="<c:url value="/acn/id/${accession.id}" />"><b><c:out value="${accession.acceNumb}" /></b></a></td>
<%-- <td><a href="<c:url value="/acn/t/${accession.taxonomy.genus}/${accession.taxonomy.species}" />"><c:out value="${accession.taxonomy.sciName}" /></a></td> --%> <%-- <td><a href="<c:url value="/acn/t/${accession.taxonomy.genus}/${accession.taxonomy.species}" />"><c:out value="${accession.taxonomy.sciName}" /></a></td> --%>
<td><c:out value="${accession.taxonomy.sciName}" /></td> <td><span dir="ltr" class="sci-name"><c:out value="${accession.taxonomy.sciName}" /></span></td>
<%-- <td class="notimportant"><a href="<c:url value="/geo/${accession.orgCty.iso3}" />"><c:out value="${accession.orgCty.name}" /></a></td> --%> <%-- <td class="notimportant"><a href="<c:url value="/geo/${accession.orgCty.iso3}" />"><c:out value="${accession.orgCty.name}" /></a></td> --%>
<td class="notimportant"><c:out value="${jspHelper.getCountry(accession.orgCty.iso3).getName(pageContext.response.locale)}" /></td> <td class="notimportant"><c:out value="${jspHelper.getCountry(accession.orgCty.iso3).getName(pageContext.response.locale)}" /></td>
<td class="notimportant"><spring:message code="accession.sampleStatus.${accession.sampStat}" /></td> <td class="notimportant"><spring:message code="accession.sampleStatus.${accession.sampStat}" /></td>
......
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<html>
<head>
<title><spring:message code="resolver.page.index.title" /></title>
</head>
<body>
<h1>
<spring:message code="resolver.page.index.title" />
</h1>
<form class="form-horizontal" method="post" role="form" action="<c:url value="/resolver/reverse" />">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<div class="form-group">
<label class="control-label col-sm-4"><spring:message code="resolver.acceNumb" /></label>