Commit a67ea924 authored by Matija Obreza's avatar Matija Obreza

Merge branch '295-accession-overview-api'

* 295-accession-overview-api:
  Accession Overview and filter suggestions API
parents 09039f24 6f3a8c85
......@@ -17,6 +17,8 @@
package org.genesys2.server.api.v1;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
......@@ -27,7 +29,10 @@ import org.genesys.catalog.service.ShortFilterService;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.service.AccessionService;
import org.genesys2.server.service.ElasticsearchService;
import org.genesys2.server.service.ElasticsearchService.TermResult;
import org.genesys2.server.service.filter.AccessionFilter;
import org.genesys2.server.service.impl.SearchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
......@@ -44,6 +49,12 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.HandlerMapping;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import com.hazelcast.util.CollectionUtil;
import io.swagger.annotations.Api;
......@@ -57,7 +68,7 @@ import io.swagger.annotations.Api;
public class AccessionController {
/** The Constant API_BASE. */
public static final String API_BASE = ApiBaseController.APIv1_BASE + "/acn";
public static final String API_BASE = ApiBaseController.APIv1_BASE + "/acn";
@Autowired
private AccessionService accessionService;
......@@ -66,6 +77,13 @@ public class AccessionController {
@Autowired
protected ShortFilterService shortFilterService;
@Autowired
private ElasticsearchService elasticsearchService;
private final Set<String> terms = Sets.newHashSet("institute.code", "institute.country.code3", "cropName", "crop.shortName", "taxonomy.genus", "taxonomy.species",
"taxonomy.genusSpecies", "countryOfOrigin.code3", "sampStat", "available", "mlsStatus", "donorCode", "sgsv", "storage", "duplSite", "breederCode");
private ObjectMapper objectMapper = new ObjectMapper();
/**
* Gets the accession
......@@ -79,23 +97,21 @@ public class AccessionController {
return accessionService.getByUuid(uuid);
}
/**
* Gets the accession
*
* @param uuid the uuid
* @return the subset
*/
@RequestMapping(value = "/10.{dummy:[0-9]+}/**", method=RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
@RequestMapping(value = "/10.{dummy:[0-9]+}/**", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Protected.class })
public Accession getByDoi(HttpServletRequest request) {
final String fullpath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
final String doi = fullpath.substring(API_BASE.length()+1);
final String doi = fullpath.substring(API_BASE.length() + 1);
return accessionService.getByDoi(doi);
}
/**
* List accessions by filterCode or filter
*
......@@ -106,17 +122,16 @@ public class AccessionController {
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws IOException
* @throws IOException
*/
@PostMapping(value = "/list", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public FilteredPage<Accession> list(@RequestParam(name = "p", required = false, defaultValue = "0") final int page,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort,
@RequestParam(name = "f", required = false) String filterCode,
@RequestParam(name = "l", required = false, defaultValue = "50") final int pageSize,
@RequestParam(name = "d", required = false, defaultValue = "ASC") final Sort.Direction direction,
@RequestParam(name = "s", required = false, defaultValue = "id") final String[] sort, @RequestParam(name = "f", required = false) String filterCode,
@RequestBody(required = false) AccessionFilter filter) throws IOException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else {
......@@ -125,4 +140,88 @@ public class AccessionController {
return new FilteredPage<>(filterCode, filter, accessionService.list(filter, new PageRequest(page, Integer.min(pageSize, 100), direction, sort)));
}
/**
* Get term overview for filters
*
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws SearchException
*/
@PostMapping(value = "/overview", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public Map<String, TermResult> overview(@RequestParam(name = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter)
throws IOException, SearchException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
return elasticsearchService.termStatisticsAuto(Accession.class, filter, 10, terms.toArray(new String[] {}));
}
/**
* Get term overview for filters
*
* @param filterCode short filter code
* @param filter the filter
* @return the page
* @throws SearchException
*/
@PostMapping(value = "/filter-suggest", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Public.class })
public Map<String, TermResult> filterSuggestions(@RequestParam(name = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter)
throws IOException, SearchException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
} else {
filterCode = shortFilterService.getCode(filter);
}
Map<String, TermResult> termResults = elasticsearchService.termStatisticsAuto(Accession.class, filter, 10, terms.toArray(new String[] {}));
// "institute.code", "institute.country.code3", "cropName", "crop.shortName",
// "taxonomy.genus", "taxonomy.genusSpecies", "taxonomy.species",
// "countryOfOrigin.code3", "sampStat", "available", "mlsStatus", "donorCode",
// "sgsv", "storage", "duplSite", "breederCode"
if (filter.taxa != null) {
if (CollectionUtil.isNotEmpty(filter.taxa.species)) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.taxa.species.clear();
termResults.put("taxonomy.species", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "taxonomy.species"));
}
if (CollectionUtil.isNotEmpty(filter.taxa.genus)) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.taxa.genus.clear();
termResults.put("taxonomy.genus", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "taxonomy.genus"));
}
}
if (filter.origin != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.origin = null;
termResults.put("countryOfOrigin.code3", elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "countryOfOrigin.code3"));
}
if (filter.holder != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.holder = null;
termResults.putAll(elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "institute.code", "institute.country.code3"));
}
if (filter.crop != null) {
AccessionFilter modifiedFilter = copyFilter(filter);
modifiedFilter.crop = null;
termResults.putAll(elasticsearchService.termStatisticsAuto(Accession.class, modifiedFilter, 10, "cropName", "crop.shortName"));
}
return termResults;
}
private AccessionFilter copyFilter(AccessionFilter filter) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
return objectMapper.readValue(objectMapper.writeValueAsString(filter), AccessionFilter.class);
}
}
......@@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.elasticsearch.index.query.QueryBuilder;
import org.genesys.blocks.model.BasicModel;
......@@ -123,13 +124,18 @@ public interface ElasticsearchService {
public static class TermResult {
private List<Term> terms;
private Long total;
private long other;
/**
* @deprecated This number is useless here and needs to be calculated based matches - total - other
*/
private Long missing;
public TermResult(String name, List<Term> terms, long other, Long missing) {
this.terms = terms;
this.total = (long) terms.size();
this.total = terms.stream().map(Term::getCount).mapToLong(Long::longValue).sum();
this.other = other;
this.missing = missing;
}
......
Markdown is supported
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