Skip to content

Commit

Permalink
WIP - further work for multi taxonomy support
Browse files Browse the repository at this point in the history
taxon depth facet support
facetting on any rank level for a checklist
query on any rank level for a checklist
#342
  • Loading branch information
djtfmartin committed Sep 17, 2024
1 parent df83959 commit dbacac7
Show file tree
Hide file tree
Showing 16 changed files with 323 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public EventSearchEs(
this.nameUsageMatchingService = nameUsageMatchingService;
eventEsFieldMapper = EventEsField.buildFieldMapper();
occurrenceEsFieldMapper = OccurrenceEventEsField.buildFieldMapper();
this.esSearchRequestBuilder = new EsSearchRequestBuilder(eventEsFieldMapper, conceptClient);
this.esSearchRequestBuilder = new EsSearchRequestBuilder(eventEsFieldMapper, conceptClient, null); ///FIXME
searchHitEventConverter = new SearchHitEventConverter(eventEsFieldMapper, true);
searchHitOccurrenceConverter = new SearchHitOccurrenceConverter(occurrenceEsFieldMapper, true);
this.esResponseParser = new EsResponseParser<>(eventEsFieldMapper, searchHitEventConverter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,18 @@ public static Predicate build(Map<String, String[]> params) {
List<Predicate> groupedByParam = new ArrayList<>();
for (Map.Entry<String,String[]> p : params.entrySet()) {
// recognize valid params by enum name, ignore others
OccurrenceSearchParameter param = toEnumParam(p.getKey());
boolean matchCase = Optional.ofNullable(params.get("matchCase")).map(vals -> Boolean.parseBoolean(vals[0])).orElse(false);
String[] values = p.getValue();
if (param != null && values != null && values.length > 0) {
// valid parameter
Predicate predicate = buildParamPredicate(param, matchCase, values);
if (predicate != null) {
groupedByParam.add(predicate);
toEnumParam(p.getKey()).ifPresent(param -> {
boolean matchCase = Optional.ofNullable(params.get("matchCase"))
.map(vals -> Boolean.parseBoolean(vals[0])).orElse(false);
String[] values = p.getValue();
if (values != null && values.length > 0) {
// valid parameter
Predicate predicate = buildParamPredicate(param, matchCase, values);
if (predicate != null) {
groupedByParam.add(predicate);
}
}
}
});
}

if (groupedByParam.isEmpty()) {
Expand All @@ -98,9 +100,9 @@ public static Predicate build(Map<String, String[]> params) {
/**
* @return the search enum or null if it cant be converted
*/
private static OccurrenceSearchParameter toEnumParam(String name) {
private static Optional<OccurrenceSearchParameter> toEnumParam(String name) {
try {
return VocabularyUtils.lookupEnum(name, OccurrenceSearchParameter.class);
return OccurrenceSearchParameter.lookup(name);
} catch (IllegalArgumentException e) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ private Optional<List<Facet<OccurrenceSearchParameter>>> parseFacets(
List<? extends Terms.Bucket> buckets = getBuckets(aggs);

// get facet of the agg
OccurrenceSearchParameter facet = occurrenceBaseEsFieldMapper.getSearchParameter(aggs.getName());
OccurrenceSearchParameter facet = occurrenceBaseEsFieldMapper.getSearchParameter(aggs.getName());
if (facet == null) {
facet = new OccurrenceSearchParameter(aggs.getName(), String.class);
}

// check for paging in facets
long facetOffset = extractFacetOffset(request, facet);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,36 +407,35 @@ private void setTaxonFields(SearchHit hit, Occurrence occ) {

private void setClassifications(SearchHit hit, Occurrence occ) {

getMapValue(hit, "classifications")
.ifPresent(
classifications -> Optional.of(classifications.entrySet().stream().map(m -> {
getMapValue(hit, "classifications").flatMap(classifications -> Optional.of(classifications.entrySet().stream().map(m -> {

String datasetKey = m.getKey();
Map<String, Object> value = (Map<String, Object>) m.getValue();
String datasetKey = m.getKey();
Map<String, Object> value = (Map<String, Object>) m.getValue();

Classification cl = new Classification();
cl.setDatasetKey(datasetKey);
Classification cl = new Classification();
cl.setDatasetKey(datasetKey);

//set the usage
Map<String, String> usage = (Map<String, String>) value.get("usage");
cl.setUsage(new RankedName(usage.get("key"), usage.get("name"), usage.get("rank"), usage.get("authorship")));
//set the usage
Map<String, String> usage = (Map<String, String>) value.get("usage");
cl.setUsage(new RankedName(usage.get("key"), usage.get("name"), usage.get("rank"), usage.get("authorship")));

//set the accepted usage
Map<String, String> acceptedusage = (Map<String, String>) value.get("acceptedUsage");
Optional.ofNullable(acceptedusage).ifPresent(au -> cl.setAcceptedUsage(new RankedName(au.get("key"), au.get("name"), au.get("rank"), au.get("authorship"))));
//set the accepted usage
Map<String, String> acceptedusage = (Map<String, String>) value.get("acceptedUsage");
Optional.ofNullable(acceptedusage).ifPresent(au -> cl.setAcceptedUsage(new RankedName(au.get("key"), au.get("name"), au.get("rank"), au.get("authorship"))));

//set the classification
Map<String, String> tree = (Map<String, String>) value.get("classification");
Map<String, String> treeKeys = (Map<String, String>) value.get("classificationKeys");
//set the classification
Map<String, String> tree = (Map<String, String>) value.get("classification");
Map<String, String> treeKeys = (Map<String, String>) value.get("classificationKeys");

cl.setIucnRedListCategory((String) value.get("iucnRedListCategory"));
cl.setIucnRedListCategory((String) value.get("iucnRedListCategory"));

cl.setClassification(
treeKeys.entrySet().stream()
.map(entry -> new RankedName((String) entry.getValue(), (String) tree.get(entry.getKey()), entry.getKey(), null))
.collect(Collectors.toList()));
return cl;
}).collect(Collectors.toList())).ifPresent(occ::setClassifications));
cl.setClassification(
treeKeys.entrySet().stream()
.map(entry -> new RankedName((String) entry.getValue(), (String) tree.get(entry.getKey()), entry.getKey(), null))
.collect(Collectors.toList())
);
return cl;
}).collect(Collectors.toList()))).ifPresent(occ::setClassifications);
}

private void setGrscicollFields(SearchHit hit, Occurrence occ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,15 @@ private static OccurrenceHeatmapRequest.Mode getMode(HttpServletRequest request)
.orElse(OccurrenceHeatmapRequest.Mode.GEO_BOUNDS);
}


private static Optional<OccurrenceSearchParameter> findSearchParam(String name) {
try {
return Optional.ofNullable((OccurrenceSearchParameter) VocabularyUtils.lookupEnum(name, OccurrenceSearchParameter.class));
return OccurrenceSearchParameter.lookup(name);
} catch (IllegalArgumentException e) {
// we have all params here, not only the enum ones, so this is ok to end up here a few times
}
return Optional.empty();
}


/**
* Removes all empty and null parameters from the list.
* Each value is trimmed(String.trim()) in order to remove all sizes of empty parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class EsHeatmapRequestBuilder {

EsHeatmapRequestBuilder(OccurrenceBaseEsFieldMapper occurrenceBaseEsFieldMapper, ConceptClient conceptClient) {
this.occurrenceBaseEsFieldMapper = occurrenceBaseEsFieldMapper;
this.esSearchRequestBuilder = new EsSearchRequestBuilder(occurrenceBaseEsFieldMapper, conceptClient);
this.esSearchRequestBuilder = new EsSearchRequestBuilder(occurrenceBaseEsFieldMapper, conceptClient, null);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
import org.gbif.ws.client.ClientBuilder;
import org.gbif.ws.json.JacksonJsonObjectMapperProvider;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import java.util.*;

/**
* Name usage match service triage.
Expand Down Expand Up @@ -51,6 +50,15 @@ public NameUsageMatchResponse match(String checklistKey, NameUsageMatchRequest m
.orElseThrow(() -> new IllegalArgumentException("No service for checklist key " + checklistKey));
}

public Collection<String> getChecklistRanks(String checklistKey) {
if (checklistKey == null) {
return List.of();
}
return Optional.ofNullable(serviceByChecklistKey.get(checklistKey))
.orElseThrow(() -> new IllegalArgumentException("No service for checklist key " + checklistKey))
.getMetadata().getMainIndex().getNameUsageByRankCount().keySet();
}

/**
* Match a name usage against the default service
* @param matchRequest the match request
Expand Down
Loading

0 comments on commit dbacac7

Please sign in to comment.