Commit 9c0022fa authored by Matija Obreza's avatar Matija Obreza
Browse files

Basic BrAPI implementation (closes #6 #7 #8)

parent 48f012a0
/*
* Copyright 2017 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.brapi.model;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.domain.Page;
/**
* BrAPI v1 response structure
*
* @author Matija Obreza
*/
public class BrAPIResponse<T> {
public Metadata metadata = new Metadata();
public Object result;
public BrAPIResponse() {
}
public BrAPIResponse(Page<T> results) {
this.result = results.getContent();
this.metadata.pagination.update(results);
}
public BrAPIResponse(Throwable exception) {
this.metadata.status.add(new Status(exception.getMessage()));
}
public BrAPIResponse(T result) {
this.result = result;
}
/**
* Response metadata
*/
public static class Metadata {
/// If no status is reported, an empty list should be returned
public List<Status> status = new ArrayList<>();
/// The datafiles key contains a list of strings. The empty list should be returned if no datafiles are present.
public List<String> datafiles = new ArrayList<>();
/// For paginated results
public Pagination pagination = new Pagination();
}
/**
* The status object contains a list of objects with the keys "code" and "message".
*/
public static class Status {
public Status(String message) {
this.message = message;
}
public Status(String code, String message) {
this.code = code;
this.message = message;
}
public String code;
public String message;
}
/**
* BrAPI pagination
*/
public static class Pagination {
public int pageSize = 0;
public int currentPage = 0;
public long totalCount = 0;
public int totalPages = 0;
/**
* Update this Pagination with information from Spring's Page<?>
*
* @param page
*/
public void update(Page<?> page) {
this.pageSize = page.getSize();
this.currentPage = page.getNumber();
this.totalPages = page.getTotalPages();
this.totalCount = page.getTotalElements();
}
}
}
package org.genesys2.brapi.model;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Germplasm as in http://docs.brapi.apiary.io/#reference/germplasm/germplasm-search-by-germplasmdbid
*
* @author Matija Obreza
*/
public class Germplasm implements Serializable {
private static final long serialVersionUID = 1L;
/// Internal db identifier Y
@JsonProperty("germplasmDbId")
private UUID uuid;
/// A string that can be displayed to the user Y
private String defaultDisplayName;
/// This is the unique identifier for accessions within a genebank, and is assigned when a sample is entered into
/// the genebank collection
@JsonProperty("accessionNumber")
private String acceNumb;
/// Name of the germplasm. It can be the prefered name and does not have to be unique
@JsonProperty("germplasmName")
private String acceName;
/// Permanent identifier (e.g. URI, DOI, LSID)
private String germplasmPUI;
/// Cross name with optional selection history.
private String pedigree;
/// Seedlot identifier
private String seedSource;
/// List of other germplasm name
private List<String> synonyms;
/// Common name for the crop (e.g. wheat, rice, maize, cassava, banana)
private String commonCropName;
/// [MCPD] Institute that has bred the material. Note: The code may consist of the 3-letter ISO 3166 country code of
/// the country where the institute is located plus a number (e.g. COL001) as recommended by FAO WIEWS Y
@JsonProperty("instituteCode")
private String instCode;
/// [MCPD] Name of the institute (or person) that bred the material.
@JsonProperty("instituteName")
private String instName;
/// [MCPD] 400) Breeding/research material 410) Breeder's line 411) Synthetic population 412) Hybrid 413) Founder
/// stock/base population 414) Inbred line (parent of hybrid cultivar) 415) Segregating population 416) Clonal
/// selection 420) Genetic stock 421) Mutant (e.g. induced/insertion mutants, tilling populations) 422) Cytogenetic
/// stocks 423) Other genetic stocks (e.g. mapping populations)500) Advanced or improved cultivar (conventional
/// breeding methods) 600) GMO (by genetic engineering) 999) Other
@JsonProperty("biologicalStatusOfAccessionCode")
private Integer sampStat;
/// [MCPD] 3-letter ISO 3166-1 code of the country in which the sample was bred or selected (breeding lines, GMOs,
/// segregating populations, hybrids, modern cultivars, etc.).
@JsonProperty("countryOfOriginCode")
private String origCty;
/// [MCPD] If germplasm is maintained under different types of storage, multiple choices are allowed. 10) Seed
/// collection 11) Short term 12) Medium term 13) Long term 20) Field collection 30) In vitro collection 40)
/// Cryopreserved collection 50) DNA collection 99) Other (elaborate in REMARKS field)
@JsonProperty("typeOfGermplasmStorageCode")
private List<Integer> storage;
/// [MCPD] Genus name for taxon. Initial uppercase letter required.
private String genus;
/// [MCPD] Specific epithet portion of the scientific name in lowercase letters.
private String species;
/// [MCPD]
@JsonProperty("speciesAuthority")
private String spAuthor;
/// [MCPD] Subtaxon can be used to store any additional taxonomic identifier. The following abbreviations are
/// allowed: ‘subsp.’ (for subspecies); ‘convar.’ (for convariety); ‘var.’ (for variety); ‘f.’ (for form); ‘Group’
/// (for ‘cultivar group’).
private String subtaxa;
private String subtAuthor;
/**
* [MCPD] code of the donor institute and Identifier assigned to an accession by the donor, and permanent
* identifier.
*/
/// donors array of object
/// [MCPD] Date on which the accession entered the collection where YYYY is the year, MM is the month and DD is the
/// day. Missing data (MM or DD) should be indicated with hyphens or ‘00’ [double zero].
@JsonProperty("acquisitionDate")
private String acqDate;
/**
* @return the uuid
*/
public UUID getUuid() {
return uuid;
}
/**
* @param uuid the uuid to set
*/
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
/**
* @return the defaultDisplayName
*/
public String getDefaultDisplayName() {
return defaultDisplayName;
}
/**
* @param defaultDisplayName the defaultDisplayName to set
*/
public void setDefaultDisplayName(String defaultDisplayName) {
this.defaultDisplayName = defaultDisplayName;
}
/**
* @return the acceNumb
*/
public String getAcceNumb() {
return acceNumb;
}
/**
* @param acceNumb the acceNumb to set
*/
public void setAcceNumb(String acceNumb) {
this.acceNumb = acceNumb;
}
/**
* @return the acceName
*/
public String getAcceName() {
return acceName;
}
/**
* @param acceName the acceName to set
*/
public void setAcceName(String acceName) {
this.acceName = acceName;
}
/**
* @return the germplasmPUI
*/
public String getGermplasmPUI() {
return germplasmPUI;
}
/**
* @param germplasmPUI the germplasmPUI to set
*/
public void setGermplasmPUI(String germplasmPUI) {
this.germplasmPUI = germplasmPUI;
}
/**
* @return the pedigree
*/
public String getPedigree() {
return pedigree;
}
/**
* @param pedigree the pedigree to set
*/
public void setPedigree(String pedigree) {
this.pedigree = pedigree;
}
/**
* @return the seedSource
*/
public String getSeedSource() {
return seedSource;
}
/**
* @param seedSource the seedSource to set
*/
public void setSeedSource(String seedSource) {
this.seedSource = seedSource;
}
/**
* @return the synonyms
*/
public List<String> getSynonyms() {
return synonyms;
}
/**
* @param synonyms the synonyms to set
*/
public void setSynonyms(List<String> synonyms) {
this.synonyms = synonyms;
}
/**
* @return the commonCropName
*/
public String getCommonCropName() {
return commonCropName;
}
/**
* @param commonCropName the commonCropName to set
*/
public void setCommonCropName(String commonCropName) {
this.commonCropName = commonCropName;
}
/**
* @return the instCode
*/
public String getInstCode() {
return instCode;
}
/**
* @param instCode the instCode to set
*/
public void setInstCode(String instCode) {
this.instCode = instCode;
}
/**
* @return the instName
*/
public String getInstName() {
return instName;
}
/**
* @param instName the instName to set
*/
public void setInstName(String instName) {
this.instName = instName;
}
/**
* @return the sampStat
*/
public Integer getSampStat() {
return sampStat;
}
/**
* @param sampStat the sampStat to set
*/
public void setSampStat(Integer sampStat) {
this.sampStat = sampStat;
}
/**
* @return the origCty
*/
public String getOrigCty() {
return origCty;
}
/**
* @param origCty the origCty to set
*/
public void setOrigCty(String origCty) {
this.origCty = origCty;
}
/**
* @return the storage
*/
public List<Integer> getStorage() {
return storage;
}
/**
* @param storage the storage to set
*/
public void setStorage(List<Integer> storage) {
this.storage = storage;
}
/**
* @return the genus
*/
public String getGenus() {
return genus;
}
/**
* @param genus the genus to set
*/
public void setGenus(String genus) {
this.genus = genus;
}
/**
* @return the species
*/
public String getSpecies() {
return species;
}
/**
* @param species the species to set
*/
public void setSpecies(String species) {
this.species = species;
}
/**
* @return the spAuthor
*/
public String getSpAuthor() {
return spAuthor;
}
/**
* @param spAuthor the spAuthor to set
*/
public void setSpAuthor(String spAuthor) {
this.spAuthor = spAuthor;
}
/**
* @return the subtaxa
*/
public String getSubtaxa() {
return subtaxa;
}
/**
* @param subtaxa the subtaxa to set
*/
public void setSubtaxa(String subtaxa) {
this.subtaxa = subtaxa;
}
/**
* @return the subtaxaAuthority
*/
public String getSubtAuthor() {
return subtAuthor;
}
/**
* @param subtaxaAuthority the subtaxaAuthority to set
*/
public void setSubtAuthor(String subtaxaAuthority) {
this.subtAuthor = subtaxaAuthority;
}
/**
* @return the acqDate
*/
public String getAcqDate() {
return acqDate;
}
/**
* @param acqDate the acqDate to set
*/
public void setAcqDate(String acqDate) {
this.acqDate = acqDate;
}
}
package org.genesys2.brapi.service;
import java.util.UUID;
import org.genesys2.brapi.model.Germplasm;
import org.genesys2.server.service.impl.NoSuchAccessionException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
/**
* BrAPI v1 services
*
* @author Matija Obreza
*/
public interface BrAPIService {
Page<String> getCrops(Pageable pageable);
Germplasm getGermplasmById(String germplasmId) throws NoSuchAccessionException;
Page<Germplasm> searchGermplasm(String germplasmName, String germplasmPUI, UUID germplasmDbId, Pageable pageable);
}
package org.genesys2.brapi.service.impl;
import java.util.Collections;
import java.util.UUID;
import java.util.stream.Collectors;
import org.elasticsearch.common.lang3.StringUtils;
import org.genesys2.brapi.model.Germplasm;
import org.genesys2.brapi.service.BrAPIService;
import org.genesys2.server.model.elastic.AccessionDetails;
import org.genesys2.server.model.elastic.Taxonomy;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Taxonomy2;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.service.CropService;
import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.GenesysFilterService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.impl.FilterHandler;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilter;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.NoSuchAccessionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Genesys implementation of BrAPI v1
*
* @author Matija Obreza
*/
@Service
@Transactional(readOnly = true)
public class BrAPIServiceImpl implements BrAPIService {
@Autowired
private GenesysFilterService filterService;
@Autowired
private GenesysService genesysService;
@Autowired
private CropService cropService;
@Override
public Germplasm getGermplasmById(String germplasmId) throws NoSuchAccessionException {
return toGermplasm(genesysService.getAccession(UUID.fromString(germplasmId)));
}
/**
* Convert Accession to Germplasm
*/
private Germplasm toGermplasm(AccessionDetails a) {
Germplasm g = new Germplasm();
g.setUuid(a.getUuid());
g.setAcceNumb(a.getAcceNumb());
g.setDefaultDisplayName(a.getAcceNumb());
g.setAcceName(a.getAcceNumb());
if (a.getAliases() != null)
g.setSynonyms(a.getAliases().stream().map(alias -> alias.getName()).collect(Collectors.toList()));
g.setPedigree(a.getPedigree());
if (a.getCrops() != null && a.getCrops().size() > 0)
g.setCommonCropName(a.getCrops().get(0));
else
g.setCommonCropName(a.getCropName());
g.setInstCode(a.getInstitute().getCode());
g.setInstName(a.getInstitute().getFullName());
g.setSampStat(a.getSampStat());
g.setOrigCty(a.getOrgCty().getIso3());
g.setStorage(a.getStorage());
Taxonomy taxonomy = a.getTaxonomy();
g.setGenus(taxonomy.getGenus());
g.setSpecies(taxonomy.getSpecies());
g.setSpAuthor(taxonomy.getSpAuthor());
g.setSubtaxa(taxonomy.getSubtaxa());
g.setSubtAuthor(taxonomy.getSubtAuthor());
g.setAcqDate(a.getAcqDate());
return g;
}