Commit 73668f45 authored by Matija Obreza's avatar Matija Obreza
Browse files

Restored trait categories (+1 squashed commit)

Squashed commits:
[1b78b4d] Added support to filter on C&E
parent e3a954b0
...@@ -43,23 +43,16 @@ public class Parameter extends VersionedAuditedModel implements AclAwareModel { ...@@ -43,23 +43,16 @@ public class Parameter extends VersionedAuditedModel implements AclAwareModel {
@JoinColumn(name = "cropId") @JoinColumn(name = "cropId")
private Crop crop; private Crop crop;
// private Category category; @ManyToOne(cascade = {}, optional = false)
@JoinColumn(name = "categoryId", nullable = false)
private ParameterCategory category;
@Column(nullable = false, length = 32) @Column(nullable = false, length = 32)
private String title; private String title;
public Parameter() { public Parameter() {
} }
// @ManyToOne(cascade = {}, optional = false)
// @JoinColumn(name = "languageId")
// public Language getLanguage() {
// return this.language;
// }
//
// public void setLanguage(final Language language) {
// this.language = language;
// }
@PrePersist @PrePersist
void ensureUUID() { void ensureUUID() {
if (this.uuid == null) { if (this.uuid == null) {
...@@ -75,15 +68,13 @@ public class Parameter extends VersionedAuditedModel implements AclAwareModel { ...@@ -75,15 +68,13 @@ public class Parameter extends VersionedAuditedModel implements AclAwareModel {
this.crop = crop; this.crop = crop;
} }
// @ManyToOne(cascade = {}, optional = false) public ParameterCategory getCategory() {
// @JoinColumn(name = "categoryId", nullable = false) return this.category;
// public Category getCategory() { }
// return this.category;
// } public void setCategory(final ParameterCategory category) {
// this.category = category;
// public void setCategory(final Category category) { }
// this.category = category;
// }
public String getTitle() { public String getTitle() {
return this.title; return this.title;
......
/**
* Copyright 2013 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.io.IOException;
import java.util.Locale;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Transient;
import org.genesys2.server.model.VersionedAuditedModel;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@Entity(name = "parametercategory")
public class ParameterCategory extends VersionedAuditedModel {
@Column(length = 100)
private String name;
@Lob
private String nameL;
@Transient
private JsonNode nameJ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameL() {
return nameL;
}
public void setNameL(String nameL) {
this.nameL = nameL;
}
public String getName(Locale locale) {
return getNameLocal(locale);
}
private synchronized String getNameLocal(Locale locale) {
if (this.nameJ == null && this.nameL != null) {
ObjectMapper mapper = new ObjectMapper();
try {
this.nameJ = mapper.readTree(nameL);
} catch (IOException e) {
e.printStackTrace();
}
}
return this.nameJ != null && this.nameJ.has(locale.getLanguage()) ? this.nameJ.get(locale.getLanguage()).textValue() : this.name;
}
}
/**
* Copyright 2013 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.ParameterCategory;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ParameterCategoryRepository extends JpaRepository<ParameterCategory, Long> {
}
...@@ -43,4 +43,6 @@ public interface TraitValueRepository { ...@@ -43,4 +43,6 @@ public interface TraitValueRepository {
*/ */
List<Object> upsert(Metadata metadata, Accession accession, Method method, List<Object> list); List<Object> upsert(Metadata metadata, Accession accession, Method method, List<Object> list);
Map<String, Long> getStatistics(Method method);
} }
\ No newline at end of file
...@@ -20,6 +20,7 @@ import java.sql.Connection; ...@@ -20,6 +20,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
...@@ -340,4 +341,16 @@ public class TraitValueRepositoryImpl implements TraitValueRepository { ...@@ -340,4 +341,16 @@ public class TraitValueRepositoryImpl implements TraitValueRepository {
return this.jdbcTemplate.queryForObject(String.format("SELECT COUNT(*) FROM `%s` WHERE metadataId=? AND accessionId=?", methodId), Integer.class, return this.jdbcTemplate.queryForObject(String.format("SELECT COUNT(*) FROM `%s` WHERE metadataId=? AND accessionId=?", methodId), Integer.class,
metadataId, accessionId); metadataId, accessionId);
} }
@Override
public Map<String, Long> getStatistics(Method method) {
final HashMap<String, Long> stats=new HashMap<String, Long>();
this.jdbcTemplate.query(MessageFormat.format("SELECT `{0}`, COUNT(*) FROM `{1,number,#}` GROUP BY `{0}`", method.getFieldName(), method.getId()), new RowCallbackHandler() {
@Override
public void processRow(ResultSet rs) throws SQLException {
stats.put(rs.getString(1), rs.getLong(2));
}
});
return stats;
}
} }
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.genesys2.server.service; package org.genesys2.server.service;
import java.util.List; import java.util.List;
import java.util.Map;
import org.genesys2.server.model.genesys.Metadata; import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method; import org.genesys2.server.model.genesys.Method;
...@@ -77,4 +78,6 @@ public interface TraitService { ...@@ -77,4 +78,6 @@ public interface TraitService {
*/ */
List<Method> listMyMethods(); List<Method> listMyMethods();
Map<String, Long> getMethodStatistics(Method method);
} }
...@@ -28,9 +28,11 @@ import org.apache.commons.lang.ArrayUtils; ...@@ -28,9 +28,11 @@ import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.genesys.Accession; import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.persistence.domain.AccessionRepository; import org.genesys2.server.persistence.domain.AccessionRepository;
import org.genesys2.server.persistence.domain.TraitValueRepository; import org.genesys2.server.persistence.domain.TraitValueRepository;
import org.genesys2.server.service.GenesysFilterService; import org.genesys2.server.service.GenesysFilterService;
import org.genesys2.server.service.TraitService;
import org.genesys2.server.service.GenesysFilterService.GenesysFilter.FilterType; import org.genesys2.server.service.GenesysFilterService.GenesysFilter.FilterType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
...@@ -59,6 +61,9 @@ public class GenesysFilterServiceImpl implements GenesysFilterService { ...@@ -59,6 +61,9 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
@Autowired @Autowired
private AccessionRepository accessionRepository; private AccessionRepository accessionRepository;
@Autowired
private TraitService traitService;
// @PersistenceContext // @PersistenceContext
// private EntityManager entityManager; // private EntityManager entityManager;
...@@ -128,6 +133,26 @@ public class GenesysFilterServiceImpl implements GenesysFilterService { ...@@ -128,6 +133,26 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
createQuery(sbf, "geo.latitude", jsonTree.get("lat"), params); createQuery(sbf, "geo.latitude", jsonTree.get("lat"), params);
createQuery(sbf, "geo.elevation", jsonTree.get("elevation"), params); createQuery(sbf, "geo.elevation", jsonTree.get("elevation"), params);
createQuery(sbf, "crop.shortName", jsonTree.get("crop"), params); createQuery(sbf, "crop.shortName", jsonTree.get("crop"), params);
for (Iterator<String> it = jsonTree.fieldNames(); it.hasNext();) {
String fieldName = it.next();
if (fieldName.startsWith("gm:")) {
LOG.info("Filtering on C&E data, method=" + fieldName);
// Handle Genesys Method!
long methodId = Long.parseLong(fieldName.substring(3));
// Need to validate method
Method method = traitService.getMethod(methodId);
if (method != null) {
String alias = "gm" + methodId;
sb.append(" inner join `").append(methodId).append("` ").append(alias).append(" on ");
sb.append(alias).append(".accessionId=a.id");
createQuery(sbf, alias + ".`" + method.getFieldName() + "`", jsonTree.get(fieldName), params);
} else {
LOG.warn("No such method with id=" + methodId);
}
}
}
sb.append(sbf.toString()); sb.append(sbf.toString());
LOG.info("Parameter count: " + params.size()); LOG.info("Parameter count: " + params.size());
......
...@@ -239,10 +239,11 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset ...@@ -239,10 +239,11 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return null; return null;
return accessionGeoRepository.findByAccession(accession); return accessionGeoRepository.findByAccession(accession);
} }
@Override @Override
public List<AccessionGeo> listAccessionsGeo(Set<Long> copy) { public List<AccessionGeo> listAccessionsGeo(Set<Long> copy) {
if (copy==null || copy.isEmpty()) return null; if (copy == null || copy.isEmpty())
return null;
return accessionGeoRepository.findForAccessions(copy); return accessionGeoRepository.findForAccessions(copy);
} }
...@@ -1124,4 +1125,12 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset ...@@ -1124,4 +1125,12 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
for (Long id : toRemove) for (Long id : toRemove)
this.accessionAliasRepository.delete(id); this.accessionAliasRepository.delete(id);
} }
@Override
public Map<String, Long> getMethodStatistics(Method method) {
if (method.isCoded()) {
return traitValueRepository.getStatistics(method);
} else
return null;
}
} }
...@@ -16,8 +16,11 @@ ...@@ -16,8 +16,11 @@
package org.genesys2.server.servlet.controller; package org.genesys2.server.servlet.controller;
import java.util.Map;
import org.genesys2.server.model.genesys.Method; import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter; import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.TraitCode;
import org.genesys2.server.service.TraitService; import org.genesys2.server.service.TraitService;
import org.genesys2.spring.ResourceNotFoundException; import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -77,6 +80,13 @@ public class DescriptorController extends BaseController { ...@@ -77,6 +80,13 @@ public class DescriptorController extends BaseController {
model.addAttribute("method", method); model.addAttribute("method", method);
model.addAttribute("metadatas", traitService.listMetadataByMethod(method)); model.addAttribute("metadatas", traitService.listMetadataByMethod(method));
if (method.isCoded()) {
Map<String, String> codeMap = TraitCode.parseCodeMap(method.getOptions());
model.addAttribute("codeMap", codeMap);
model.addAttribute("codeStatistics", traitService.getMethodStatistics(method));
}
return "/descr/method"; return "/descr/method";
} }
} }
...@@ -183,7 +183,7 @@ accession.duplSite=Safety duplication ...@@ -183,7 +183,7 @@ accession.duplSite=Safety duplication
accession.inSvalbard=Svalbardized accession.inSvalbard=Svalbardized
accession.inTrust.true=This accession is under Article 15 of the International Treaty on Plant Genetic Resources for Food and Agriculture. accession.inTrust.true=This accession is under Article 15 of the International Treaty on Plant Genetic Resources for Food and Agriculture.
accession.mlsStatus.true=This accession is in the Multilateral System of the ITPGRFA. accession.mlsStatus.true=This accession is in the Multilateral System of the ITPGRFA.
accession.inSvalbard.true=Super-safety duplicated in Svalbard Seed Vault. accession.inSvalbard.true=Safety duplicated in Svalbard Seed Vault.
accession.not-available-for-distribution=The accession is NOT available for distribution. accession.not-available-for-distribution=The accession is NOT available for distribution.
accession.available-for-distribution=The accession is available for distribution. accession.available-for-distribution=The accession is available for distribution.
accession.elevation=Elevation accession.elevation=Elevation
...@@ -430,3 +430,6 @@ userprofile.email.send=Send email ...@@ -430,3 +430,6 @@ userprofile.email.send=Send email
verification.invalid-key=Token key is not valid. verification.invalid-key=Token key is not valid.
verification.token-key=Validation key verification.token-key=Validation key
login.invalid-token=Invalid access token login.invalid-token=Invalid access token
descriptor.category=Descriptor category
method.coding-table=Coding table
\ No newline at end of file
...@@ -171,7 +171,7 @@ accession.mlsStatus=Statut MLS ...@@ -171,7 +171,7 @@ accession.mlsStatus=Statut MLS
# accession.inSvalbard=Svalbardized # accession.inSvalbard=Svalbardized
accession.inTrust.true=L'accession est sous l'article 15 du traité international sur les ressources phytogénétiques pour l'alimentation et l'agriculture. accession.inTrust.true=L'accession est sous l'article 15 du traité international sur les ressources phytogénétiques pour l'alimentation et l'agriculture.
accession.mlsStatus.true=Ce numéro se trouve dans le Système multilatéral du TIRPAA. accession.mlsStatus.true=Ce numéro se trouve dans le Système multilatéral du TIRPAA.
accession.inSvalbard.true=Super-sécurité dupliquée dans la Réserve mondiale de semences du Svalbard. accession.inSvalbard.true=Sécurité dupliquée dans la Réserve mondiale de semences du Svalbard.
# accession.not-available-for-distribution=The accession is NOT available for distribution. # accession.not-available-for-distribution=The accession is NOT available for distribution.
# accession.available-for-distribution=The accession is available for distribution. # accession.available-for-distribution=The accession is available for distribution.
# accession.elevation=Elevation # accession.elevation=Elevation
......
...@@ -171,7 +171,7 @@ accession.mlsStatus=Estado MLS ...@@ -171,7 +171,7 @@ accession.mlsStatus=Estado MLS
accession.inSvalbard=Svalbardizado accession.inSvalbard=Svalbardizado
accession.inTrust.true=Esta adesão está sob o Artigo 15 do Tratado Internacional de Recursos Genéticos Vegetais para Comida e Agricultura. accession.inTrust.true=Esta adesão está sob o Artigo 15 do Tratado Internacional de Recursos Genéticos Vegetais para Comida e Agricultura.
accession.mlsStatus.true=Esta adesão pertence ao Sistema Multilateral do ITPGRFA. accession.mlsStatus.true=Esta adesão pertence ao Sistema Multilateral do ITPGRFA.
accession.inSvalbard.true=Super-segurança duplicada no Cofre de Sementes de Svalbard. accession.inSvalbard.true=Segurança duplicada no Cofre de Sementes de Svalbard.
# accession.not-available-for-distribution=The accession is NOT available for distribution. # accession.not-available-for-distribution=The accession is NOT available for distribution.
# accession.available-for-distribution=The accession is available for distribution. # accession.available-for-distribution=The accession is available for distribution.
# accession.elevation=Elevation # accession.elevation=Elevation
......
...@@ -50,7 +50,7 @@ cdn.base=http://cdn.sandbox.genesys-pgr.org ...@@ -50,7 +50,7 @@ cdn.base=http://cdn.sandbox.genesys-pgr.org
cdn.flags.url=${cdn.base}/flags cdn.flags.url=${cdn.base}/flags
# Content creation on startup # Content creation on startup
auto.createContent=true auto.createContent=false
# Mail properties # Mail properties
mail.host=localhost mail.host=localhost
......
...@@ -12,7 +12,10 @@ ...@@ -12,7 +12,10 @@
<small>${trait.crop.getName(pageContext.response.locale)}</small> <small>${trait.crop.getName(pageContext.response.locale)}</small>
</h1> </h1>
<div> <div>
<spring:message code="filter.crop" />: <b><a href="<c:url value="/c/${trait.crop.shortName}" />">${trait.crop.getName(pageContext.response.locale)}</a></b> <spring:message code="filter.crop" />: <b><a href="<c:url value="/c/${trait.crop.shortName}/descriptors" />">${trait.crop.getName(pageContext.response.locale)}</a></b>
</div>
<div>
<spring:message code="descriptor.category" />: <c:out value="${trait.category.getName(pageContext.response.locale)}" />
</div> </div>
<h4> <h4>
<spring:message code="ce.methods" /> <spring:message code="ce.methods" />
......
...@@ -11,17 +11,21 @@ ...@@ -11,17 +11,21 @@
<spring:message code="trait-list" /> <spring:message code="trait-list" />
</h1> </h1>
<div class="main-col-header clearfix">
<div class="nav-header pull-left">
<div class="results"><spring:message code="paged.totalElements" arguments="${pagedData.totalElements}" /></div>
<div class="pagination">
<spring:message code="paged.pageOfPages" arguments="${pagedData.number+1},${pagedData.totalPages}" />
<a class="${pagedData.number eq 0 ? 'disabled' :''}" href="?page=${pagedData.number eq 0 ? 1 : pagedData.number}"><spring:message code="pagination.previous-page" /></a> <a href="?page=${pagedData.number + 2}"><spring:message code="pagination.next-page" /></a>
</div>
</div>
</div>
<c:if test="${crop ne null}"> <c:if test="${crop ne null}">
<div> <div class="applied-filters">
<spring:message code="filter.crop" />: <b><a href="<c:url value="/c/${crop.shortName}" />">${crop.getName(pageContext.response.locale)}</a></b> <spring:message code="filter.crop" />: <b><a href="<c:url value="/c/${crop.shortName}" />">${crop.getName(pageContext.response.locale)}</a></b>
</div> </div>
</c:if> </c:if>
<div class="nav-header">
<spring:message code="paged.totalElements" arguments="${pagedData.totalElements}" />
<br />
<spring:message code="paged.pageOfPages" arguments="${pagedData.number+1},${pagedData.totalPages}" />
<a class="${pagedData.number eq 0 ? 'disabled' :''}" href="?page=${pagedData.number eq 0 ? 1 : pagedData.number}"><spring:message code="pagination.previous-page" /></a> <a href="?page=${pagedData.number + 2}"><spring:message code="pagination.next-page" /></a>
</div>
<table class="accessions"> <table class="accessions">
<thead> <thead>
...@@ -29,6 +33,7 @@ ...@@ -29,6 +33,7 @@
<td class="idx-col" /> <td class="idx-col" />
<td>Trait</td> <td>Trait</td>
<td>Crop</td> <td>Crop</td>
<td><spring:message code="descriptor.category" /></td>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -37,6 +42,7 @@ ...@@ -37,6 +42,7 @@
<td class="idx-col">${status.count + pagedData.size * pagedData.number}</td> <td class="idx-col">${status.count + pagedData.size * pagedData.number}</td>
<td><a href="<c:url value="/descriptors/${trait.id}" />">${trait.title}</a></td> <td><a href="<c:url value="/descriptors/${trait.id}" />">${trait.title}</a></td>
<td><a href="<c:url value="/c/${trait.crop.shortName}" />">${trait.crop.getName(pageContext.response.locale)}</a></td> <td><a href="<c:url value="/c/${trait.crop.shortName}" />">${trait.crop.getName(pageContext.response.locale)}</a></td>
<td><c:out value="${trait.category.getName(pageContext.response.locale)}" /></td>
</tr> </tr>
</c:forEach> </c:forEach>
</tbody> </tbody>
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
<h1> <h1>
<c:out value="${trait.title}" /> <c:out value="${trait.title}" />
</h1> </h1>
<div>
<spring:message code="filter.crop" />: <b><a href="<c:url value="/c/${trait.crop.shortName}/descriptors" />">${trait.crop.getName(pageContext.response.locale)}</a></b>
</div>
<table> <table>
<tbody> <tbody>
<tr> <tr>
...@@ -21,16 +23,35 @@ ...@@ -21,16 +23,35 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<c:if test="${method.coded}">
<h3><spring:message code="method.coding-table" /></h3>
<ul class="funny-list">
<c:forEach items="${codeMap.keySet()}" var="key" varStatus="status">
<li class="${status.count % 2 == 0 ? 'even' : 'odd'}">
<span class="method-code"><c:out value="${key}" /></span>
<a title="<spring:message code="view.accessions" />" href="<c:url value="/acn/f"><c:param name="filter">{"gm:${method.id}":["${key}"]}</c:param></c:url>">
<c:out value="${codeMap[key]}" />
</a>
count=${codeStatistics[key]}
</li>
</c:forEach>
</ul>
</c:if>
<h3><spring:message code="accession.metadatas" /></h3> <h3><spring:message code="accession.metadatas" /></h3>
<ul class="funny-list"> <ul class="funny-list">
<c:forEach items="${metadatas}" var="metadata" varStatus="status"> <c:forEach items="${metadatas}" var="metadata" varStatus="status">
<li class="clearfix ${status.count % 2 == 0 ? 'even' : 'odd'}"><a class="show pull-left" href="/data/view/${metadata.id}"><c:out value="${metadata.title}" /></a> <li class="clearfix ${status.count % 2 == 0 ? 'even' : 'odd'}">
<a class="show pull-left" href="/data/view/${metadata.id}"><c:out value="${metadata.title}" /></a>
<div class="pull-right"> <div class="pull-right">
<c:out value="${metadata.instituteCode}" /> <c:out value="${metadata.instituteCode}" />
</div></li> </div></li>
</c:forEach> </c:forEach>
</ul> </ul>
<style>
span.method-code { font-weight: bold; font-size: 110%; margin-left: 2em; float: right; }
</stlye>
</body> </body>
</html> </html>
\ No newline at end of file