package org.gbif.checklistbank.service.mybatis; import org.gbif.api.exception.UnparsableException; import org.gbif.api.model.checklistbank.Description; import org.gbif.api.model.checklistbank.Distribution; import org.gbif.api.model.checklistbank.NameUsage; import org.gbif.api.model.checklistbank.NameUsageMediaObject; import org.gbif.api.model.checklistbank.NameUsageMetrics; import org.gbif.api.model.checklistbank.ParsedName; import org.gbif.api.model.checklistbank.SpeciesProfile; import org.gbif.api.model.checklistbank.VerbatimNameUsage; import org.gbif.api.model.checklistbank.VernacularName; import org.gbif.api.model.common.Identifier; import org.gbif.api.model.common.LinneanClassificationKeys; import org.gbif.api.service.checklistbank.NameParser; import org.gbif.api.service.checklistbank.NameUsageService; import org.gbif.api.util.ClassificationUtils; import org.gbif.api.vocabulary.CitesAppendix; import org.gbif.api.vocabulary.Country; import org.gbif.api.vocabulary.Language; import org.gbif.api.vocabulary.LifeStage; import org.gbif.api.vocabulary.NameUsageIssue; import org.gbif.api.vocabulary.NomenclaturalStatus; import org.gbif.api.vocabulary.OccurrenceStatus; import org.gbif.api.vocabulary.Origin; import org.gbif.api.vocabulary.Rank; import org.gbif.api.vocabulary.TaxonomicStatus; import org.gbif.api.vocabulary.ThreatStatus; import org.gbif.checklistbank.model.UsageExtensions; import org.gbif.checklistbank.service.UsageSyncService; import org.gbif.checklistbank.service.mybatis.postgres.ClbDbTestRule; import org.gbif.dwc.terms.DwcTerm; import org.gbif.nameparser.GBIFNameParser; import java.net.URI; import java.util.Date; import java.util.List; import java.util.UUID; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; /** * */ public class UsageSyncServiceMyBatisIT extends MyBatisServiceITBase<UsageSyncService> { public UsageSyncServiceMyBatisIT() { super(UsageSyncService.class); } private static final NameParser PARSER = new GBIFNameParser(); NameUsageService uService; @Before public void init2() { uService = getInstance(NameUsageService.class); } @Test public void testDeleteDataset() throws Exception { int num = service.deleteDataset(ClbDbTestRule.SQUIRRELS_DATASET_KEY); assertEquals(44, num); } @Test public void testSyncUsage() throws Exception { // first add a classification to please constraints NameUsage k = addHigher(1, null, null, "Plantae", Rank.KINGDOM); NameUsage p = addHigher(2, k.getKey(), k, "Pinophyta", Rank.PHYLUM); NameUsage c = addHigher(3, p.getKey(), p, "Pinopsida", Rank.CLASS); NameUsage o = addHigher(4, c.getKey(), c, "Pinales", Rank.ORDER); NameUsage f = addHigher(5, o.getKey(), o, "Pinaceae", Rank.FAMILY); NameUsage g = addHigher(6, f.getKey(), f, "Abies", Rank.GENUS); // create rather complete usage to sync WITHOUT a KEY final String taxonID = "gfzd8"; String name = "Abies alba Mill."; NameUsage u = new NameUsage(); u.setDatasetKey(ClbDbTestRule.SQUIRRELS_DATASET_KEY); u.setScientificName(name); u.setTaxonID(taxonID); u.setOrigin(Origin.SOURCE); u.getIssues().add(NameUsageIssue.MULTIMEDIA_INVALID); u.getIssues().add(NameUsageIssue.CHAINED_SYNOYM); u.setModified(new Date()); u.getNomenclaturalStatus().add(NomenclaturalStatus.CONSERVED); u.getNomenclaturalStatus().add(NomenclaturalStatus.DOUBTFUL); u.setRank(Rank.SUBSPECIES); u.setRemarks("neat neat neat"); u.setTaxonomicStatus(TaxonomicStatus.DOUBTFUL); u.setSourceTaxonKey(674321); u.setReferences(URI.create("http://www.gbif.org/1234")); u.setAccordingTo("Chuck told me this"); u.setNumDescendants(321); u.setNubKey(p.getKey()); UsageExtensions e = new UsageExtensions(); e.descriptions.add(buildDescription()); e.distributions.add(buildDistribution()); e.identifiers.add(buildIdentifier()); e.speciesProfiles.add(buildSpeciesProfile()); e.vernacularNames.add(buildVernacularName()); NameUsageMetrics m = new NameUsageMetrics(); m.setNumSpecies(1); m.setNumDescendants(4); m.setNumSynonyms(3); u.setParentKey(g.getKey()); u.setBasionymKey(-1); // point to itself! u.setProParteKey(-1); // point to itself! u.setKingdomKey(k.getKey()); u.setPhylumKey(p.getKey()); u.setClassKey(c.getKey()); u.setOrderKey(o.getKey()); u.setFamilyKey(f.getKey()); u.setGenusKey(g.getKey()); u.setSpeciesKey(u.getKey()); int k1 = service.syncUsage(false, u, PARSER.parse(u.getScientificName(), u.getRank()), m); // verify props NameUsage u2 = uService.get(k1, null); assertEquals(k.getKey(), u2.getKingdomKey()); assertEquals(p.getKey(), u2.getPhylumKey()); assertEquals(c.getKey(), u2.getClassKey()); assertEquals(o.getKey(), u2.getOrderKey()); assertEquals(f.getKey(), u2.getFamilyKey()); assertEquals(g.getKey(), u2.getGenusKey()); assertEquals(g.getKey(), u2.getParentKey()); assertEquals((Integer) k1, u2.getBasionymKey()); assertEquals((Integer) k1, u2.getProParteKey()); assertEquals(u.getTaxonID(), u2.getTaxonID()); assertEquals(u.getScientificName(), u2.getScientificName()); assertEquals(u.getIssues(), u2.getIssues()); assertEquals(ClbDbTestRule.SQUIRRELS_DATASET_KEY, u2.getDatasetKey()); assertEquals(u.getTaxonomicStatus(), u2.getTaxonomicStatus()); assertEquals(u.getAccordingTo(), u2.getAccordingTo()); assertEquals(u.getRemarks(), u2.getRemarks()); assertEquals(u.getOrigin(), u2.getOrigin()); assertNotNull(u2.getLastInterpreted()); assertEquals(u.getModified(), u2.getModified()); assertEquals(p.getKey(), u2.getNubKey()); assertEquals(u.getSourceTaxonKey(), u2.getSourceTaxonKey()); // Try an update now with verbatim data (remove usage key as we detect existing record by taxonID only!) u.setKey(null); u.setBasionymKey(-1); // point to itself! u.setProParteKey(-1); // point to itself! m.setKey(null); VerbatimNameUsage v = new VerbatimNameUsage(); v.setCoreField(DwcTerm.scientificName, name); v.setCoreField(DwcTerm.taxonID, taxonID); int k2 = service.syncUsage(false, u, PARSER.parse(u.getScientificName(), u.getRank()), m); service.syncUsageExtras(false, ClbDbTestRule.SQUIRRELS_DATASET_KEY, u.getKey(), v, e); assertEquals(k1, k2); // verify props u2 = uService.get(k1, null); assertEquals(k.getKey(), u2.getKingdomKey()); assertEquals(p.getKey(), u2.getPhylumKey()); assertEquals(c.getKey(), u2.getClassKey()); assertEquals(o.getKey(), u2.getOrderKey()); assertEquals(f.getKey(), u2.getFamilyKey()); assertEquals(g.getKey(), u2.getGenusKey()); assertEquals(g.getKey(), u2.getParentKey()); assertEquals((Integer) k1, u2.getBasionymKey()); assertEquals((Integer) k1, u2.getProParteKey()); assertEquals(p.getKey(), u2.getNubKey()); } /** * Makes sure all db enums are matching the API enum values */ @Test public void testAllEnums() throws Exception { String name = "Abies mekka Jesus"; NameUsage u = new NameUsage(); u.setDatasetKey(ClbDbTestRule.SQUIRRELS_DATASET_KEY); u.setScientificName(name); u.setOrigin(Origin.SOURCE); u.setModified(new Date()); // all enums u.getIssues().addAll(Sets.newHashSet(NameUsageIssue.values())); u.getNomenclaturalStatus().addAll(Sets.newHashSet(NomenclaturalStatus.values())); u.setRank(Rank.SPECIES); u.setTaxonomicStatus(TaxonomicStatus.ACCEPTED); NameUsageMetrics m = new NameUsageMetrics(); ParsedName pn = PARSER.parse(u.getScientificName(), u.getRank()); final int uID = service.syncUsage(false, u, pn, m); List<Integer> ids = Lists.newArrayList(uID); for (Rank r : Rank.values()) { m.setKey(null); u.setKey(null); u.setRank(r); // there are far more ranks than status values if (r.ordinal() < TaxonomicStatus.values().length) { u.setTaxonomicStatus(TaxonomicStatus.values()[r.ordinal()]); } ids.add(service.syncUsage(true, u, pn, m)); } NameUsage u2 = uService.get(uID, null); u2.setLastInterpreted(null); u2.setNameKey(null); u2.setCanonicalName(null); u2.setNameType(null); u2.setAuthorship(null); u.setKey(uID); u.setRank(Rank.SPECIES); u.setTaxonomicStatus(TaxonomicStatus.ACCEPTED); assertEquals(u, u2); } private NameUsage addHigher(int key, Integer parentKey, LinneanClassificationKeys higherKeys, String name, Rank rank) throws UnparsableException { NameUsage p = new NameUsage(); p.setDatasetKey(ClbDbTestRule.SQUIRRELS_DATASET_KEY); p.setKey(key); p.setParentKey(parentKey); if (higherKeys != null) { ClassificationUtils.copyLinneanClassificationKeys(higherKeys, p); } // add link to oneself if (rank.isLinnean()) { ClassificationUtils.setHigherRankKey(p, rank, key); } p.setScientificName(name); p.setRank(rank); p.setTaxonID(name); p.setTaxonomicStatus(TaxonomicStatus.ACCEPTED); p.setOrigin(Origin.SOURCE); p.setLastInterpreted(new Date()); p.setModified(new Date()); NameUsageMetrics m = new NameUsageMetrics(); m.setKey(key); service.syncUsage(false, p, PARSER.parse(p.getScientificName(), p.getRank()), m); return p; } private Description buildDescription() { Description d = new Description(); d.setLicense("my licsnse"); d.setLanguage(Language.ABKHAZIAN); d.setSource("mz source"); d.setCreator("markus"); d.setType("headline"); d.setDescription("nothing to read"); return d; } private Distribution buildDistribution() { Distribution d = new Distribution(); d.setSource("my source"); d.setLifeStage(LifeStage.ADULT); d.setThreatStatus(ThreatStatus.CRITICALLY_ENDANGERED); d.setStatus(OccurrenceStatus.ABSENT); d.setTemporal("temp"); d.setStartDayOfYear(12); d.setEndDayOfYear(23); d.setLocationId("tdwg:ARG"); d.setLocality("Somewhere in Argentinia"); d.setAppendixCites(CitesAppendix.II); d.setCountry(Country.ARGENTINA); d.setSourceTaxonKey(123); return d; } private Identifier buildIdentifier() { Identifier i = new Identifier(); return i; } private NameUsageMediaObject buildMedia() { NameUsageMediaObject i = new NameUsageMediaObject(); return i; } private SpeciesProfile buildSpeciesProfile() { SpeciesProfile i = new SpeciesProfile(); return i; } private VernacularName buildVernacularName() { VernacularName i = new VernacularName(); return i; } }