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 UUID key for the dataset registered in GBIF.
082   */
083  datasetKey(GbifTerm.GROUP_DATASET),
084
085  /**
086   * The ISO 3166 2-letter code of the country of the organization that publishes the dataset to which the occurrence belongs.
087   */
088  publishingCountry(GbifTerm.GROUP_DATASET),
089
090  /**
091   * Numerical, stable identifier assigned by GBIF to an Occurrence record.
092   */
093  gbifID(DwcTerm.GROUP_OCCURRENCE),
094
095  /**
096   * Timestamp of the last time the record was (re)interpreted by GBIF.
097   */
098  lastInterpreted(DwcTerm.GROUP_OCCURRENCE),
099
100  /**
101   * The uncertainty radius for the latitude and longitude in decimal degrees.
102   */
103  @Deprecated
104  coordinateAccuracy(DwcTerm.GROUP_OCCURRENCE),
105
106  /**
107   * Elevation in metres above sea level (altitude).
108   * <p>
109   * The elevation is the absolute vertical position of the observed location (z-coordinate).
110   * If depth is given or not will not impact the 3-dimensional position.
111   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
112   * an elevation of 1900.
113   * </p>
114   * <p>
115   * If minimum and maximum values are given the elevation is calculated using the equation:
116   * <code>(minimumElevationInMeters + maximumElevationInMeters) / 2</code>.
117   * For consistency and ease of use GBIF decided to always use a value in metres plus its accuracy instead of
118   * min/max values which are sometimes used in Darwin Core. See also depth & distanceAboveSurface.
119   * </p>
120   */
121  elevation(DwcTerm.GROUP_LOCATION),
122
123  /**
124   * Elevation accuracy is the uncertainty for the elevation in metres.
125   * <p>
126   * The elevation accuracy is calculated using the equation: <code>(maximumElevationInMeters - minimumElevationInMeters) / 2</code>
127   * in case a minimum and maximum verbatim value is given.
128   * </p>
129   */
130  elevationAccuracy(DwcTerm.GROUP_LOCATION),
131
132  /**
133   * Depth in metres below the surface.
134   * <p>
135   * Complimentary and relative to elevation, depth indicates the distance to the earth surface, whether that is water
136   * or ground.
137   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
138   * an elevation of 1900.
139   * </p>
140   * <p>
141   * The depth is calculated using the equation: <code>(minimumDepthInMeters + maximumDepthInMeters) / 2</code>.
142   * For consistency and ease of use GBIF decided to always use a value in meters plus it's accuracy instead of
143   * min/max values which are sometimes used in Darwin Core. See also elevation & distanceAboveSurface.
144   * </p>
145   */
146  depth(DwcTerm.GROUP_LOCATION),
147
148  /**
149   * Depth accuracy is the uncertainty for the depth in metres.
150   * <p>
151   * The depth accuracy is calculated using the equation: <code>(maximumDepthInMeters - minimumDepthInMeters) / 2</code>
152   * in case a minimum and maximum verbatim value is given.
153   * </p>
154   */
155  depthAccuracy(DwcTerm.GROUP_LOCATION),
156
157  /**
158   * Replaced by Darwin Core terms <a href="http://rs.tdwg.org/dwc/terms/minimumDistanceAboveSurfaceInMeters">dwc:minimumDistanceAboveSurfaceInMeters</a>
159   * and <a href="http://rs.tdwg.org/dwc/terms/maximumDistanceAboveSurfaceInMeters">dwc:maximumDistanceAboveSurfaceInMeters</a>.
160   */
161  @Deprecated
162  distanceAboveSurface(DwcTerm.GROUP_LOCATION),
163
164  /**
165   * Replaced by Darwin Core terms <a href="http://rs.tdwg.org/dwc/terms/minimumDistanceAboveSurfaceInMeters">dwc:minimumDistanceAboveSurfaceInMeters</a>
166   * and <a href="http://rs.tdwg.org/dwc/terms/maximumDistanceAboveSurfaceInMeters">dwc:maximumDistanceAboveSurfaceInMeters</a>.
167   */
168  @Deprecated
169  distanceAboveSurfaceAccuracy(DwcTerm.GROUP_LOCATION),
170
171  /**
172   * The distance in metres from a known centroid, e.g. a country centroid.
173   */
174  distanceFromCentroidInMeters(DwcTerm.GROUP_LOCATION),
175
176  /**
177   * Any issue found during processing and interpretation or the record.
178   * See <a href="https://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/OccurrenceIssue.html">OccurrenceIssue enumeration</a> for possible values.
179   */
180  issue(DwcTerm.GROUP_OCCURRENCE),
181
182  /**
183   * Issue found during processing and interpretation or the record related to a specific checklist.
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  taxonomicIssue(DwcTerm.GROUP_OCCURRENCE),
187
188  /**
189   * Issue found during processing and interpretation or the record that are non-taxonomic.
190   */
191  nonTaxonomicIssue(DwcTerm.GROUP_OCCURRENCE),
192
193  /**
194   * The media type given as Dublin Core type values, in particular StillImage, MovingImage or Sound.
195   */
196  mediaType(DwcTerm.GROUP_OCCURRENCE),
197
198  // experimental Occurrence properties
199  infraspecificMarker(DwcTerm.GROUP_OCCURRENCE),
200
201  // Types and Specimen checklist extension
202  typeDesignatedBy(DwcTerm.GROUP_OCCURRENCE),
203  typeDesignationType(DwcTerm.GROUP_OCCURRENCE),
204
205  /**
206   * Boolean indicating that a valid latitude and longitude exists.
207   * Even if existing it might still have issues, see hasGeospatialIssues and issue.
208   */
209  hasCoordinate(DwcTerm.GROUP_OCCURRENCE),
210
211  /**
212   * Boolean indicating that some spatial validation rule has not passed.
213   * Primarily used to indicate that the record should not be displayed on a map.
214   */
215  hasGeospatialIssues(DwcTerm.GROUP_OCCURRENCE),
216
217
218  /**
219   * The checklist key.
220   * <p>
221   * The taxonomic checklist to use when search using a taxonKey, a higher taxonKey e.g. phylumKey
222   * or when searching with a scientific name
223   * </p>
224   */
225  checklistKey(DwcTerm.GROUP_TAXON),
226
227  /**
228   * The GBIF backbone key.
229   * <p>
230   * The best matching, accepted GBIF backbone name usage representing this occurrence.
231   * In case the verbatim scientific name and its classification can only be matched to a higher rank this will
232   * represent the lowest matching rank. In the worst case this could just be for example Animalia.
233   * </p>
234   * <p>
235   * In contrast dwc:taxonID is only used for the source ids similar to occurrenceID
236   * </p>
237   */
238  taxonKey(DwcTerm.GROUP_TAXON),
239
240
241  /**
242   * The GBIF backbone key of the accepted taxon key.
243   */
244  acceptedTaxonKey(DwcTerm.GROUP_TAXON),
245
246  /**
247   * The key to the accepted kingdom in the GBIF backbone.
248   */
249  kingdomKey(DwcTerm.GROUP_TAXON),
250
251  /**
252   * The key to the accepted phylum in the GBIF backbone.
253   */
254  phylumKey(DwcTerm.GROUP_TAXON),
255
256  /**
257   * The key to the accepted class in the GBIF backbone.
258   */
259  classKey(DwcTerm.GROUP_TAXON),
260
261  /**
262   * The key to the accepted order in the GBIF backbone.
263   */
264  orderKey(DwcTerm.GROUP_TAXON),
265
266  /**
267   * The key to the accepted family in the GBIF backbone.
268   */
269  familyKey(DwcTerm.GROUP_TAXON),
270
271  /**
272   * The key to the accepted genus in the GBIF backbone.
273   */
274  genusKey(DwcTerm.GROUP_TAXON),
275
276  /**
277   * The key to the accepted subgenus in the GBIF backbone.
278   */
279  subgenusKey(DwcTerm.GROUP_TAXON),
280
281  /**
282   * The backbone key to the accepted species.
283   * In case the taxonKey is of a higher rank than species (e.g. genus) speciesKey is null.
284   * In case taxonKey represents an infraspecific taxon the speciesKey points to the species
285   * the infraspecies is classified as. In case of taxonKey being a species the speciesKey is the same.
286   */
287  speciesKey(DwcTerm.GROUP_TAXON),
288
289  /**
290   * The canonical name without authorship of the accepted species.
291   */
292  species(DwcTerm.GROUP_TAXON),
293
294  // experimental Taxon properties
295  canonicalName(DwcTerm.GROUP_TAXON),
296  nameType(DwcTerm.GROUP_TAXON),
297
298  /**
299   * The scientific name the type associated acceptedNubKey.
300   */
301  acceptedScientificName(DwcTerm.GROUP_TAXON),
302
303  /**
304   * Scientific name as provided by the source.
305   */
306  verbatimScientificName(DwcTerm.GROUP_TAXON),
307
308  /**
309   * The scientific name the type status of this specimen applies to.
310   * Term proposed in Darwin Core, but not yet ratified.
311   */
312  typifiedName(DwcTerm.GROUP_IDENTIFICATION),
313
314  /**
315   * The kind of protocol used when the record was last crawled by GBIF.
316   * See <a href="http://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/EndpointType.html">EndpointType enumeration</a> for possible values.
317   */
318  protocol(GbifTerm.GROUP_CRAWLING),
319
320  /**
321   * The date this record was last parsed from raw xml/json into a verbatim GBIF record.
322   */
323  lastParsed(GbifTerm.GROUP_CRAWLING),
324
325  /**
326   * The date this record was last crawled/harvested by GBIF from the endpoint.
327   */
328  lastCrawled(GbifTerm.GROUP_CRAWLING),
329
330  // Species Profile checklist extension
331  isMarine(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
332  isFreshwater(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
333  isTerrestrial(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
334  isInvasive(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
335  isHybrid(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
336  isExtinct(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
337  livingPeriod(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "timePeriod"),
338  ageInDays(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
339  sizeInMillimeters(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "sizeInMillimeter"),
340  massInGrams(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "massInGram", "weightInGram"),
341  lifeForm(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
342
343  // Vernacular Name checklist extension
344  organismPart(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
345  isPlural(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
346  isPreferredName(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
347
348  // Distribution checklist extension
349  appendixCITES(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
350  numberOfOccurrences(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
351
352  /** Boolean indicating if the publishing country is different to the location country. */
353  repatriated(DwcTerm.GROUP_OCCURRENCE),
354
355  /** Calculated relative organism quantity, based on organism and sample measure types */
356  relativeOrganismQuantity(DwcTerm.GROUP_MATERIAL_SAMPLE),
357
358  /** An identifier for a project to which a record belongs. */
359  projectId(DwcTerm.GROUP_OCCURRENCE),
360
361  /** Flag occurrence when associatedSequences/extension exists */
362  isSequenced(DwcTerm.GROUP_OCCURRENCE),
363
364  /** GBIF region based on country code */
365  gbifRegion(DwcTerm.GROUP_LOCATION),
366
367  /** GBIF region based on publishing country code */
368  publishedByGbifRegion(DwcTerm.GROUP_LOCATION),
369  geologicalTime(DwcTerm.GROUP_OCCURRENCE),
370  lithostratigraphy(DwcTerm.GROUP_OCCURRENCE),
371  biostratigraphy(DwcTerm.GROUP_OCCURRENCE),
372  dnaSequenceID(GbifTerm.GROUP_DNA_DERIVED_DATA);
373
374  private static final String PREFIX = "gbif";
375  private static final String NS = "http://rs.gbif.org/terms/1.0/";
376  private static final URI NS_URI = URI.create(NS);
377
378  public static final String GROUP_CRAWLING = "Crawling";
379  public static final String GROUP_DATASET = "Dataset";
380  public static final String GROUP_ROW_TYPE = "RowType";
381  public static final String GROUP_SPECIES_DISTRIBUTION_EXTENSION = "SpeciesDistribution";
382  public static final String GROUP_SPECIES_PROFILE_EXTENSION = "SpeciesProfile";
383  public static final String GROUP_VERNACULAR_NAME_EXTENSION = "VernacularName";
384  public static final String GROUP_DNA_DERIVED_DATA = "DnaDerivedData";
385
386  /**
387   * Lists all GBIF term groups.
388   */
389  public static final String[] GROUPS = {GROUP_CRAWLING, GROUP_DATASET, DwcTerm.GROUP_OCCURRENCE, GROUP_ROW_TYPE,
390    GROUP_SPECIES_DISTRIBUTION_EXTENSION, GROUP_SPECIES_PROFILE_EXTENSION, DwcTerm.GROUP_TAXON,
391    GROUP_VERNACULAR_NAME_EXTENSION, DwcTerm.GROUP_LOCATION};
392
393  /**
394   * Lists all GBIF terms in taxon group.
395   */
396  public static final GbifTerm[] TAXONOMIC_TERMS =
397  {GbifTerm.checklistKey, GbifTerm.taxonKey, GbifTerm.acceptedTaxonKey, GbifTerm.kingdomKey, GbifTerm.phylumKey, GbifTerm.classKey,
398   GbifTerm.orderKey, GbifTerm.familyKey, GbifTerm.genusKey, GbifTerm.subgenusKey, GbifTerm.speciesKey,
399   GbifTerm.species, GbifTerm.canonicalName, GbifTerm.nameType, GbifTerm.acceptedScientificName,
400   GbifTerm.verbatimScientificName};
401
402  private final String groupName;
403  private final boolean isDeprecated;
404  public final String[] normAlts;
405
406  GbifTerm(String groupName, String... alternatives) {
407    this.groupName = groupName;
408    this.normAlts = alternatives;
409    boolean deprecatedAnnotationPresent = false;
410    try {
411      deprecatedAnnotationPresent = GbifTerm.class.getField(this.name()).isAnnotationPresent(Deprecated.class);
412    } catch (NoSuchFieldException ignore) { }
413    this.isDeprecated = deprecatedAnnotationPresent;
414  }
415
416  /**
417   * The simple term name without a namespace.
418   * For example taxonKey.
419   *
420   * @return simple term name
421   */
422  @Override
423  public String simpleName() {
424    return name();
425  }
426
427  /**
428   * Array of alternative simple names in use for the term.
429   *
430   * @return simple term name
431   */
432  @Override
433  public String[] alternativeNames() {
434    return normAlts;
435  }
436
437  /**
438   * The optional group the term is grouped in.
439   * For example Occurrence, Taxon, etc.
440   */
441  public String getGroup() {
442    return groupName;
443  }
444
445
446  /**
447   * List all terms that belong to a given group.
448   *
449   * @param group the group to list terms for
450   * @return the list of GBIF terms in the given group
451   */
452  public static List<GbifTerm> listByGroup(String group) {
453    List<GbifTerm> terms = new ArrayList<GbifTerm>();
454    for (GbifTerm t : GbifTerm.values()) {
455      if (t.getGroup().equalsIgnoreCase(group)) {
456        terms.add(t);
457      }
458    }
459    return terms;
460  }
461
462  @Override
463  public String toString() {
464    return prefixedName();
465  }
466
467  @Override
468  public boolean isClass() {
469    return Character.isUpperCase(simpleName().charAt(0));
470  }
471
472  @Override
473  public String prefix() {
474    return PREFIX;
475  }
476
477  @Override
478  public URI namespace() {
479    return NS_URI;
480  }
481
482  /**
483   *
484   * @return true if the Term is annotated with @Deprecated.
485   */
486  public boolean isDeprecated(){
487    return isDeprecated;
488  }
489
490}