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  isTerrestrial(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
333  isFreshwater(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
334  isHybrid(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
335  isExtinct(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
336  livingPeriod(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "timePeriod"),
337  lifeForm(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
338  ageInDays(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
339  sizeInMillimeter(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
340  massInGram(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "weightInGram"),
341
342  // Vernacular Name checklist extension
343  organismPart(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
344  isPlural(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
345  isPreferredName(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
346
347  // Distribution checklist extension
348  appendixCITES(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
349  numberOfOccurrences(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
350
351  /** Boolean indicating if the publishing country is different to the location country. */
352  repatriated(DwcTerm.GROUP_OCCURRENCE),
353
354  /** Calculated relative organism quantity, based on organism and sample measure types */
355  relativeOrganismQuantity(DwcTerm.GROUP_MATERIAL_SAMPLE),
356
357  /** An identifier for a project to which a record belongs. */
358  projectId(DwcTerm.GROUP_OCCURRENCE),
359
360  /** Flag occurrence when associatedSequences/extension exists */
361  isSequenced(DwcTerm.GROUP_OCCURRENCE),
362
363  /** GBIF region based on country code */
364  gbifRegion(DwcTerm.GROUP_LOCATION),
365
366  /** GBIF region based on publishing country code */
367  publishedByGbifRegion(DwcTerm.GROUP_LOCATION),
368  geologicalTime(DwcTerm.GROUP_OCCURRENCE),
369  lithostratigraphy(DwcTerm.GROUP_OCCURRENCE),
370  biostratigraphy(DwcTerm.GROUP_OCCURRENCE),
371  dnaSequenceID(GbifTerm.GROUP_DNA_DERIVED_DATA);
372
373  private static final String PREFIX = "gbif";
374  private static final String NS = "http://rs.gbif.org/terms/1.0/";
375  private static final URI NS_URI = URI.create(NS);
376
377  public static final String GROUP_CRAWLING = "Crawling";
378  public static final String GROUP_DATASET = "Dataset";
379  public static final String GROUP_ROW_TYPE = "RowType";
380  public static final String GROUP_SPECIES_DISTRIBUTION_EXTENSION = "SpeciesDistribution";
381  public static final String GROUP_SPECIES_PROFILE_EXTENSION = "SpeciesProfile";
382  public static final String GROUP_VERNACULAR_NAME_EXTENSION = "VernacularName";
383  public static final String GROUP_DNA_DERIVED_DATA = "DnaDerivedData";
384
385  /**
386   * Lists all GBIF term groups.
387   */
388  public static final String[] GROUPS = {GROUP_CRAWLING, GROUP_DATASET, DwcTerm.GROUP_OCCURRENCE, GROUP_ROW_TYPE,
389    GROUP_SPECIES_DISTRIBUTION_EXTENSION, GROUP_SPECIES_PROFILE_EXTENSION, DwcTerm.GROUP_TAXON,
390    GROUP_VERNACULAR_NAME_EXTENSION, DwcTerm.GROUP_LOCATION};
391
392  /**
393   * Lists all GBIF terms in taxon group.
394   */
395  public static final GbifTerm[] TAXONOMIC_TERMS =
396  {GbifTerm.checklistKey, GbifTerm.taxonKey, GbifTerm.acceptedTaxonKey, GbifTerm.kingdomKey, GbifTerm.phylumKey, GbifTerm.classKey,
397   GbifTerm.orderKey, GbifTerm.familyKey, GbifTerm.genusKey, GbifTerm.subgenusKey, GbifTerm.speciesKey,
398   GbifTerm.species, GbifTerm.canonicalName, GbifTerm.nameType, GbifTerm.acceptedScientificName,
399   GbifTerm.verbatimScientificName};
400
401  private final String groupName;
402  private final boolean isDeprecated;
403  public final String[] normAlts;
404
405  GbifTerm(String groupName, String... alternatives) {
406    this.groupName = groupName;
407    this.normAlts = alternatives;
408    boolean deprecatedAnnotationPresent = false;
409    try {
410      deprecatedAnnotationPresent = GbifTerm.class.getField(this.name()).isAnnotationPresent(Deprecated.class);
411    } catch (NoSuchFieldException ignore) { }
412    this.isDeprecated = deprecatedAnnotationPresent;
413  }
414
415  /**
416   * The simple term name without a namespace.
417   * For example taxonKey.
418   *
419   * @return simple term name
420   */
421  @Override
422  public String simpleName() {
423    return name();
424  }
425
426  /**
427   * Array of alternative simple names in use for the term.
428   *
429   * @return simple term name
430   */
431  @Override
432  public String[] alternativeNames() {
433    return normAlts;
434  }
435
436  /**
437   * The optional group the term is grouped in.
438   * For example Occurrence, Taxon, etc.
439   */
440  public String getGroup() {
441    return groupName;
442  }
443
444
445  /**
446   * List all terms that belong to a given group.
447   *
448   * @param group the group to list terms for
449   * @return the list of GBIF terms in the given group
450   */
451  public static List<GbifTerm> listByGroup(String group) {
452    List<GbifTerm> terms = new ArrayList<GbifTerm>();
453    for (GbifTerm t : GbifTerm.values()) {
454      if (t.getGroup().equalsIgnoreCase(group)) {
455        terms.add(t);
456      }
457    }
458    return terms;
459  }
460
461  @Override
462  public String toString() {
463    return prefixedName();
464  }
465
466  @Override
467  public boolean isClass() {
468    return Character.isUpperCase(simpleName().charAt(0));
469  }
470
471  @Override
472  public String prefix() {
473    return PREFIX;
474  }
475
476  @Override
477  public URI namespace() {
478    return NS_URI;
479  }
480
481  /**
482   *
483   * @return true if the Term is annotated with @Deprecated.
484   */
485  public boolean isDeprecated(){
486    return isDeprecated;
487  }
488
489}