001/*
002 * Copyright 2021 Global Biodiversity Information Facility (GBIF)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.gbif.dwc.terms;
017
018import java.io.Serializable;
019import java.net.URI;
020import java.util.ArrayList;
021import java.util.List;
022
023public enum GbifTerm implements Term, AlternativeNames, Serializable {
024  // row types
025
026  /**
027   * The <a href="http://rs.gbif.org/terms/1.0/Description">GBIF Taxon Description</a>
028   * extension row type.
029   */
030  Description(GbifTerm.GROUP_ROW_TYPE),
031
032  /**
033   * The <a href="http://rs.gbif.org/terms/1.0/Distribution">GBIF Species Distribution</a>
034   * extension row type.
035   */
036  Distribution(GbifTerm.GROUP_ROW_TYPE),
037
038  /**
039   * The <a href="http://rs.gbif.org/terms/1.0/Identifier">GBIF Alternative Identifiers</a>
040   * extension row type.
041   */
042  Identifier(GbifTerm.GROUP_ROW_TYPE),
043
044  /**
045   * The deprecated <a href="http://rs.gbif.org/terms/1.0/Image">GBIF Simple Images</a>
046   * extension row type.
047   */
048  Image(GbifTerm.GROUP_ROW_TYPE, "Images"),
049
050  /**
051   * The <a href="http://rs.gbif.org/terms/1.0/References">GBIF Literature References</a>
052   * extension row type.
053   */
054  Reference(GbifTerm.GROUP_ROW_TYPE, "References"),
055
056  /**
057   * The <a href="http://rs.gbif.org/terms/1.0/SpeciesProfile">GBIF Species Profile</a>
058   * extension row type.
059   */
060  SpeciesProfile(GbifTerm.GROUP_ROW_TYPE, "SpeciesMiniProfile", "SpeciesInfo", "SpeciesData", "SpeciesFactsheet"),
061
062  /**
063   * The <a href="http://rs.gbif.org/terms/1.0/TypesAndSpecimen">GBIF Types and Specimen</a>
064   * extension row type.
065   */
066  TypesAndSpecimen(GbifTerm.GROUP_ROW_TYPE, "Specimen", "Types", "TypeDesignation"),
067
068  /**
069   * The <a href="http://rs.gbif.org/terms/1.0/VernacularNames">GBIF Vernacular Names</a>
070   * extension row type.
071   */
072  VernacularName(GbifTerm.GROUP_ROW_TYPE, "VernacularNames", "Vernacular", "Vernaculars"),
073
074  /**
075   * The <a href="http://rs.gbif.org/terms/1.0/Multimedia">GBIF Simple Multimedia</a>
076   * extension row type.
077   */
078  Multimedia(GbifTerm.GROUP_ROW_TYPE),
079
080  /**
081   * The <a href="http://rs.gbif.org/terms/1.0/DNADerivedData">DNA Derived Data</a>
082   * extension row type.
083   */
084  DNADerivedData(GbifTerm.GROUP_ROW_TYPE),
085
086  /**
087   * The UUID key for the dataset registered in GBIF.
088   */
089  datasetKey(GbifTerm.GROUP_DATASET),
090
091  /**
092   * The ISO 3166 2-letter code of the country of the organization that publishes the dataset to which the occurrence belongs.
093   */
094  publishingCountry(GbifTerm.GROUP_DATASET),
095
096  /**
097   * Numerical, stable identifier assigned by GBIF to an Occurrence record.
098   */
099  gbifID(DwcTerm.GROUP_OCCURRENCE),
100
101  /**
102   * Timestamp of the last time the record was (re)interpreted by GBIF.
103   */
104  lastInterpreted(DwcTerm.GROUP_OCCURRENCE),
105
106  /**
107   * The uncertainty radius for the latitude and longitude in decimal degrees.
108   */
109  @Deprecated
110  coordinateAccuracy(DwcTerm.GROUP_OCCURRENCE),
111
112  /**
113   * Elevation in metres above sea level (altitude).
114   * <p>
115   * The elevation is the absolute vertical position of the observed location (z-coordinate).
116   * If depth is given or not will not impact the 3-dimensional position.
117   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
118   * an elevation of 1900.
119   * </p>
120   * <p>
121   * If minimum and maximum values are given the elevation is calculated using the equation:
122   * <code>(minimumElevationInMeters + maximumElevationInMeters) / 2</code>.
123   * For consistency and ease of use GBIF decided to always use a value in metres plus its accuracy instead of
124   * min/max values which are sometimes used in Darwin Core. See also depth & distanceAboveSurface.
125   * </p>
126   */
127  elevation(DwcTerm.GROUP_LOCATION),
128
129  /**
130   * Elevation accuracy is the uncertainty for the elevation in metres.
131   * <p>
132   * The elevation accuracy is calculated using the equation: <code>(maximumElevationInMeters - minimumElevationInMeters) / 2</code>
133   * in case a minimum and maximum verbatim value is given.
134   * </p>
135   */
136  elevationAccuracy(DwcTerm.GROUP_LOCATION),
137
138  /**
139   * Depth in metres below the surface.
140   * <p>
141   * Complimentary and relative to elevation, depth indicates the distance to the earth surface, whether that is water
142   * or ground.
143   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
144   * an elevation of 1900.
145   * </p>
146   * <p>
147   * The depth is calculated using the equation: <code>(minimumDepthInMeters + maximumDepthInMeters) / 2</code>.
148   * For consistency and ease of use GBIF decided to always use a value in meters plus it's accuracy instead of
149   * min/max values which are sometimes used in Darwin Core. See also elevation & distanceAboveSurface.
150   * </p>
151   */
152  depth(DwcTerm.GROUP_LOCATION),
153
154  /**
155   * Depth accuracy is the uncertainty for the depth in metres.
156   * <p>
157   * The depth accuracy is calculated using the equation: <code>(maximumDepthInMeters - minimumDepthInMeters) / 2</code>
158   * in case a minimum and maximum verbatim value is given.
159   * </p>
160   */
161  depthAccuracy(DwcTerm.GROUP_LOCATION),
162
163  /**
164   * Replaced by Darwin Core terms <a href="http://rs.tdwg.org/dwc/terms/minimumDistanceAboveSurfaceInMeters">dwc:minimumDistanceAboveSurfaceInMeters</a>
165   * and <a href="http://rs.tdwg.org/dwc/terms/maximumDistanceAboveSurfaceInMeters">dwc:maximumDistanceAboveSurfaceInMeters</a>.
166   */
167  @Deprecated
168  distanceAboveSurface(DwcTerm.GROUP_LOCATION),
169
170  /**
171   * Replaced by Darwin Core terms <a href="http://rs.tdwg.org/dwc/terms/minimumDistanceAboveSurfaceInMeters">dwc:minimumDistanceAboveSurfaceInMeters</a>
172   * and <a href="http://rs.tdwg.org/dwc/terms/maximumDistanceAboveSurfaceInMeters">dwc:maximumDistanceAboveSurfaceInMeters</a>.
173   */
174  @Deprecated
175  distanceAboveSurfaceAccuracy(DwcTerm.GROUP_LOCATION),
176
177  /**
178   * The distance in metres from a known centroid, e.g. a country centroid.
179   */
180  distanceFromCentroidInMeters(DwcTerm.GROUP_LOCATION),
181
182  /**
183   * Any issue found during processing and interpretation or the record.
184   * See <a href="https://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/OccurrenceIssue.html">OccurrenceIssue enumeration</a> for possible values.
185   */
186  issue(DwcTerm.GROUP_OCCURRENCE),
187
188  /**
189   * Issue found during processing and interpretation or the record related to a specific checklist.
190   * See <a href="https://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/OccurrenceIssue.html">OccurrenceIssue enumeration</a> for possible values.
191   */
192  taxonomicIssue(DwcTerm.GROUP_OCCURRENCE),
193
194  /**
195   * Issue found during processing and interpretation or the record that are non-taxonomic.
196   */
197  nonTaxonomicIssue(DwcTerm.GROUP_OCCURRENCE),
198
199  /**
200   * The media type given as Dublin Core type values, in particular StillImage, MovingImage or Sound.
201   */
202  mediaType(DwcTerm.GROUP_OCCURRENCE),
203
204  // experimental Occurrence properties
205  infraspecificMarker(DwcTerm.GROUP_OCCURRENCE),
206
207  // Types and Specimen checklist extension
208  typeDesignatedBy(DwcTerm.GROUP_OCCURRENCE),
209  typeDesignationType(DwcTerm.GROUP_OCCURRENCE),
210
211  /**
212   * Boolean indicating that a valid latitude and longitude exists.
213   * Even if existing it might still have issues, see hasGeospatialIssues and issue.
214   */
215  hasCoordinate(DwcTerm.GROUP_OCCURRENCE),
216
217  /**
218   * Boolean indicating that some spatial validation rule has not passed.
219   * Primarily used to indicate that the record should not be displayed on a map.
220   */
221  hasGeospatialIssues(DwcTerm.GROUP_OCCURRENCE),
222
223
224  /**
225   * The checklist key.
226   * <p>
227   * The taxonomic checklist to use when search using a taxonKey, a higher taxonKey e.g. phylumKey
228   * or when searching with a scientific name
229   * </p>
230   */
231  checklistKey(DwcTerm.GROUP_TAXON),
232
233  /**
234   * The GBIF backbone key.
235   * <p>
236   * The best matching, accepted GBIF backbone name usage representing this occurrence.
237   * In case the verbatim scientific name and its classification can only be matched to a higher rank this will
238   * represent the lowest matching rank. In the worst case this could just be for example Animalia.
239   * </p>
240   * <p>
241   * In contrast dwc:taxonID is only used for the source ids similar to occurrenceID
242   * </p>
243   */
244  taxonKey(DwcTerm.GROUP_TAXON),
245
246
247  /**
248   * The GBIF backbone key of the accepted taxon key.
249   */
250  acceptedTaxonKey(DwcTerm.GROUP_TAXON),
251
252  /**
253   * The key to the accepted kingdom in the taxonomy.
254   */
255  kingdomKey(DwcTerm.GROUP_TAXON),
256
257  /**
258   * The key to the accepted phylum in the taxonomy.
259   */
260  phylumKey(DwcTerm.GROUP_TAXON),
261
262  /**
263   * The key to the accepted class in the taxonomy.
264   */
265  classKey(DwcTerm.GROUP_TAXON),
266
267  /**
268   * The key to the accepted order in the taxonomy.
269   */
270  orderKey(DwcTerm.GROUP_TAXON),
271
272  /**
273   * The key to the accepted superfamily in the taxonomy.
274   */
275  superfamilyKey(DwcTerm.GROUP_TAXON),
276
277  /**
278   * The key to the accepted family in the taxonomy.
279   */
280  familyKey(DwcTerm.GROUP_TAXON),
281
282  /**
283   * The key to the accepted subfamily in the taxonomy.
284   */
285  subfamilyKey(DwcTerm.GROUP_TAXON),
286
287  /**
288   * The key to the accepted tribe in the taxonomy.
289   */
290  tribeKey(DwcTerm.GROUP_TAXON),
291
292  /**
293   * The key to the accepted subtribe in the taxonomy.
294   */
295  subtribeKey(DwcTerm.GROUP_TAXON),
296
297    /**
298   * The key to the accepted genus in the taxonomy.
299   */
300  genusKey(DwcTerm.GROUP_TAXON),
301
302  /**
303   * The key to the accepted subgenus in the taxonomy.
304   */
305  subgenusKey(DwcTerm.GROUP_TAXON),
306
307  /**
308   * The backbone key to the accepted species.
309   * In case the taxonKey is of a higher rank than species (e.g. genus) speciesKey is null.
310   * In case taxonKey represents an infraspecific taxon the speciesKey points to the species
311   * the infraspecies is classified as. In case of taxonKey being a species the speciesKey is the same.
312   */
313  speciesKey(DwcTerm.GROUP_TAXON),
314
315  /**
316   * The canonical name without authorship of the accepted species.
317   */
318  species(DwcTerm.GROUP_TAXON),
319
320  // experimental Taxon properties
321  canonicalName(DwcTerm.GROUP_TAXON),
322  nameType(DwcTerm.GROUP_TAXON),
323
324  /**
325   * The scientific name the type associated acceptedNubKey.
326   */
327  acceptedScientificName(DwcTerm.GROUP_TAXON),
328
329  /**
330   * Scientific name as provided by the source.
331   */
332  verbatimScientificName(DwcTerm.GROUP_TAXON),
333
334  /**
335   * The scientific name the type status of this specimen applies to.
336   * Term proposed in Darwin Core, but not yet ratified.
337   */
338  typifiedName(DwcTerm.GROUP_IDENTIFICATION),
339
340  /**
341   * The kind of protocol used when the record was last crawled by GBIF.
342   * See <a href="http://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/EndpointType.html">EndpointType enumeration</a> for possible values.
343   */
344  protocol(GbifTerm.GROUP_CRAWLING),
345
346  /**
347   * The date this record was last parsed from raw xml/json into a verbatim GBIF record.
348   */
349  lastParsed(GbifTerm.GROUP_CRAWLING),
350
351  /**
352   * The date this record was last crawled/harvested by GBIF from the endpoint.
353   */
354  lastCrawled(GbifTerm.GROUP_CRAWLING),
355
356  // Species Profile checklist extension
357  isMarine(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
358  isFreshwater(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
359  isTerrestrial(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
360  isInvasive(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
361  isHybrid(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
362  isExtinct(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
363  livingPeriod(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "timePeriod"),
364  ageInDays(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
365  sizeInMillimeters(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "sizeInMillimeter"),
366  massInGrams(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "massInGram", "weightInGram"),
367  lifeForm(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
368
369  // Vernacular Name checklist extension
370  organismPart(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
371  isPlural(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
372  isPreferredName(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
373
374  // Distribution checklist extension
375  appendixCITES(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
376  numberOfOccurrences(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
377
378  /** Boolean indicating if the publishing country is different to the location country. */
379  repatriated(DwcTerm.GROUP_OCCURRENCE),
380
381  /** Calculated relative organism quantity, based on organism and sample measure types */
382  relativeOrganismQuantity(DwcTerm.GROUP_MATERIAL_SAMPLE),
383
384  /** An identifier for a project to which a record belongs. */
385  projectId(DwcTerm.GROUP_OCCURRENCE),
386
387  /** Flag occurrence when associatedSequences/extension exists */
388  isSequenced(DwcTerm.GROUP_OCCURRENCE),
389
390  /** GBIF region based on country code */
391  gbifRegion(DwcTerm.GROUP_LOCATION),
392
393  /** GBIF region based on publishing country code */
394  publishedByGbifRegion(DwcTerm.GROUP_LOCATION),
395  geologicalTime(DwcTerm.GROUP_OCCURRENCE),
396  lithostratigraphy(DwcTerm.GROUP_OCCURRENCE),
397  biostratigraphy(DwcTerm.GROUP_OCCURRENCE),
398  dnaSequenceID(GbifTerm.GROUP_DNA_DERIVED_DATA),
399
400  /**
401   * The <a href="http://rs.tdwg.org/eco/terms/Event">Humboldt</a> extension row type.
402   */
403  Humboldt(GbifTerm.GROUP_ROW_TYPE);
404
405  private static final String PREFIX = "gbif";
406  private static final String NS = "http://rs.gbif.org/terms/1.0/";
407  private static final URI NS_URI = URI.create(NS);
408
409  public static final String GROUP_CRAWLING = "Crawling";
410  public static final String GROUP_DATASET = "Dataset";
411  public static final String GROUP_ROW_TYPE = "RowType";
412  public static final String GROUP_SPECIES_DISTRIBUTION_EXTENSION = "SpeciesDistribution";
413  public static final String GROUP_SPECIES_PROFILE_EXTENSION = "SpeciesProfile";
414  public static final String GROUP_VERNACULAR_NAME_EXTENSION = "VernacularName";
415  public static final String GROUP_DNA_DERIVED_DATA = "DnaDerivedData";
416  public static final String GROUP_HUMBOLDT = "Humboldt";
417
418  /**
419   * Lists all GBIF term groups.
420   */
421  public static final String[] GROUPS = {GROUP_CRAWLING, GROUP_DATASET, DwcTerm.GROUP_OCCURRENCE, GROUP_ROW_TYPE,
422    GROUP_SPECIES_DISTRIBUTION_EXTENSION, GROUP_SPECIES_PROFILE_EXTENSION, DwcTerm.GROUP_TAXON,
423    GROUP_VERNACULAR_NAME_EXTENSION, DwcTerm.GROUP_LOCATION};
424
425  /**
426   * Lists all GBIF terms in taxon group.
427   */
428  public static final GbifTerm[] TAXONOMIC_TERMS =
429  {GbifTerm.checklistKey, GbifTerm.taxonKey, GbifTerm.acceptedTaxonKey, GbifTerm.kingdomKey, GbifTerm.phylumKey,
430   GbifTerm.classKey, GbifTerm.orderKey, GbifTerm.superfamilyKey, GbifTerm.familyKey, GbifTerm.subfamilyKey,
431   GbifTerm.tribeKey, GbifTerm.subtribeKey, GbifTerm.genusKey, GbifTerm.subgenusKey, GbifTerm.speciesKey,
432   GbifTerm.species, GbifTerm.canonicalName, GbifTerm.nameType, GbifTerm.acceptedScientificName,
433   GbifTerm.verbatimScientificName};
434
435  private final String groupName;
436  private final boolean isDeprecated;
437  public final String[] normAlts;
438
439  GbifTerm(String groupName, String... alternatives) {
440    this.groupName = groupName;
441    this.normAlts = alternatives;
442    boolean deprecatedAnnotationPresent = false;
443    try {
444      deprecatedAnnotationPresent = GbifTerm.class.getField(this.name()).isAnnotationPresent(Deprecated.class);
445    } catch (NoSuchFieldException ignore) { }
446    this.isDeprecated = deprecatedAnnotationPresent;
447  }
448
449  /**
450   * The simple term name without a namespace.
451   * For example taxonKey.
452   *
453   * @return simple term name
454   */
455  @Override
456  public String simpleName() {
457    return name();
458  }
459
460  /**
461   * Array of alternative simple names in use for the term.
462   *
463   * @return simple term name
464   */
465  @Override
466  public String[] alternativeNames() {
467    return normAlts;
468  }
469
470  /**
471   * The optional group the term is grouped in.
472   * For example Occurrence, Taxon, etc.
473   */
474  public String getGroup() {
475    return groupName;
476  }
477
478
479  /**
480   * List all terms that belong to a given group.
481   *
482   * @param group the group to list terms for
483   * @return the list of GBIF terms in the given group
484   */
485  public static List<GbifTerm> listByGroup(String group) {
486    List<GbifTerm> terms = new ArrayList<GbifTerm>();
487    for (GbifTerm t : GbifTerm.values()) {
488      if (t.getGroup().equalsIgnoreCase(group)) {
489        terms.add(t);
490      }
491    }
492    return terms;
493  }
494
495  @Override
496  public String toString() {
497    return prefixedName();
498  }
499
500  @Override
501  public boolean isClass() {
502    return Character.isUpperCase(simpleName().charAt(0));
503  }
504
505  @Override
506  public String prefix() {
507    return PREFIX;
508  }
509
510  @Override
511  public URI namespace() {
512    return NS_URI;
513  }
514
515  /**
516   *
517   * @return true if the Term is annotated with @Deprecated.
518   */
519  public boolean isDeprecated(){
520    return isDeprecated;
521  }
522
523}