package org.gbif.nub.lookup.straight;
import org.gbif.api.model.checklistbank.NameUsageMatch;
import org.gbif.api.model.common.LinneanClassification;
import org.gbif.api.service.checklistbank.NameUsageMatchingService;
import org.gbif.api.vocabulary.Kingdom;
import org.gbif.api.vocabulary.Rank;
import org.gbif.checklistbank.authorship.AuthorComparator;
import org.gbif.checklistbank.ws.client.guice.ChecklistBankWsClientModule;
import org.gbif.checklistbank.ws.client.guice.ChecklistBankWsMatchClientModule;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.annotation.Nullable;
import com.google.common.collect.Lists;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Implementation of an IdLookup using the nub matching webservice.
*/
public class IdLookupWs implements IdLookup {
NameUsageMatchingService service;
public static IdLookupWs create(String apiRootUrl) {
Properties props = new Properties();
props.setProperty(ChecklistBankWsMatchClientModule.PROPERTY_API_URL, apiRootUrl);
return new IdLookupWs(props);
}
public IdLookupWs(Properties props) {
ChecklistBankWsClientModule module = new ChecklistBankWsClientModule(props, false, true);
Injector inj = Guice.createInjector(module);
service = inj.getInstance(NameUsageMatchingService.class);
}
@Override
public LookupUsage match(String canonicalName, Rank rank, Kingdom kingdom) {
return match(canonicalName, null, null, rank, kingdom);
}
@Override
public LookupUsage match(String canonicalName, @Nullable String authorship, @Nullable String year, Rank rank, Kingdom kingdom) {
return usage(service.match(concatName(canonicalName, authorship, year), rank, classification(kingdom), true, false));
}
@Override
public List<LookupUsage> match(String canonicalName) {
List<LookupUsage> matches = Lists.newArrayList();
NameUsageMatch match = service.match(canonicalName, null, null, true, true);
if (match != null) {
if (match.getUsageKey() != null) {
matches.add(usage(match));
// add alternatives
for (NameUsageMatch alt : match.getAlternatives()) {
matches.add(usage(alt));
}
}
}
return matches;
}
private static String concatName(String canonical, String authorship, String year) {
StringBuilder name = new StringBuilder();
name.append(canonical);
if (authorship != null) {
name.append(" ");
name.append(authorship);
if (year != null) {
name.append(",");
}
}
if (year != null) {
name.append(" ");
name.append(year);
}
return name.toString();
}
private static LinneanClassification classification(Kingdom kingdom) {
LinneanClassification cl = new NameUsageMatch();
cl.setKingdom(kingdom.scientificName());
return cl;
}
private static LookupUsage usage(NameUsageMatch match) {
LookupUsage u = null;
if (match != null && match.getUsageKey() != null) {
u = new LookupUsage();
u.setKey(match.getUsageKey());
u.setCanonical(match.getCanonicalName());
u.setRank(match.getRank());
u.setAuthorship(extractAuthor(match.getScientificName(), match.getCanonicalName()));
u.setYear(extractYear(match.getScientificName(), match.getCanonicalName()));
if (match.getKingdomKey() != null) {
u.setKingdom(Kingdom.byNubUsageKey(match.getKingdomKey()));
} else {
u.setKingdom(Kingdom.INCERTAE_SEDIS);
}
u.setDeleted(false);
}
return u;
}
private static String extractAuthor(String sciname, String canonical) {
// be simple, remove last canonical epithet from sciname
String author = null;
return author;
}
private static String extractYear(String sciname, String canonical) {
// ignore year for now...
return null;
}
@Override
public int size() {
throw new UnsupportedOperationException("The webservice lookup can only query backbone names");
}
@Override
public int deletedIds() {
throw new UnsupportedOperationException("The webservice lookup can only query backbone names");
}
@Override
public Iterator<LookupUsage> iterator() {
throw new UnsupportedOperationException("The webservice lookup can only query backbone names");
}
@Nullable
@Override
public AuthorComparator getAuthorComparator() {
throw new UnsupportedOperationException("The webservice lookup can only query backbone names");
}
@Override
public void close() throws Exception {
// nothing to do
}
}