001package org.gbif.dwc.terms;
002
003import java.io.Serializable;
004import java.net.URI;
005import java.util.ArrayList;
006import java.util.List;
007
008public enum GbifTerm implements Term, AlternativeNames, Serializable {
009  // row types
010  Description(GbifTerm.GROUP_ROW_TYPE),
011  Distribution(GbifTerm.GROUP_ROW_TYPE),
012  Identifier(GbifTerm.GROUP_ROW_TYPE),
013  Image(GbifTerm.GROUP_ROW_TYPE, "Images"),
014  Reference(GbifTerm.GROUP_ROW_TYPE, "References"),
015  SpeciesProfile(GbifTerm.GROUP_ROW_TYPE, "SpeciesMiniProfile", "SpeciesInfo", "SpeciesData", "SpeciesFactsheet"),
016  TypesAndSpecimen(GbifTerm.GROUP_ROW_TYPE, "Specimen", "Types", "TypeDesignation"),
017  VernacularName(GbifTerm.GROUP_ROW_TYPE, "VernacularNames", "Vernacular", "Vernaculars"),
018  Multimedia(GbifTerm.GROUP_ROW_TYPE),
019
020  /**
021   * The UUID key for the dataset registered in GBIF.
022   */
023  datasetKey(GbifTerm.GROUP_DATASET),
024
025  /**
026   * The ISO code of the country of the organization that publishes the dataset to which the occurrence belongs.
027   */
028  publishingCountry(GbifTerm.GROUP_DATASET),
029
030  /**
031   * Numerical, stable identifier assigned by GBIF to an Occurrence record.
032   */
033  gbifID(DwcTerm.GROUP_OCCURRENCE),
034
035  /**
036   * Timestamp of the last time the record has been (re)interpreted by GBIF.
037   */
038  lastInterpreted(DwcTerm.GROUP_OCCURRENCE),
039
040  /**
041   * The uncertainty radius for lat/lon in decimal degrees.
042   */
043  @Deprecated
044  coordinateAccuracy(DwcTerm.GROUP_OCCURRENCE),
045
046  /**
047   * Elevation in meters above sea level (altitude).
048   * <p>
049   * The elevation is the absolute vertical position of the observed location (z-coordinate).
050   * If depth is given or not will not impact the 3-dimensional position.
051   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
052   * an elevation of 1900.
053   * </p>
054   * <p>
055   * If minimum and maximum values are given the elevation is calculated using the equation:
056   * (minimumElevationInMeters + maximumElevationInMeters) / 2.
057   * For consistency and ease of use GBIF decided to always use a value in meters plus it's accurracy instead of
058   * min/max values which are sometimes used in Darwin Core. See also depth & distanceAboveSurface.
059   * </p>
060   */
061  elevation(DwcTerm.GROUP_LOCATION),
062
063  /**
064   * Elevation accuracy is the uncertainty for the elevation in meters.
065   * <p>
066   * The elevation accuracy is calculated using the equation: (maximumElevationInMeters - minimumElevationInMeters) / 2
067   * in case a minimum and maximum verbatim value is given.
068   * </p>
069   */
070  elevationAccuracy(DwcTerm.GROUP_LOCATION),
071
072  /**
073   * Depth in meters below the surface.
074   * <p>
075   * Complimentary and relative to elevation, depth indicates the distance to the earth surface, whether that is water
076   * or ground.
077   * For example a location 100m below the surface of a lake in 2000m altitude has a depth of 100 and
078   * an elevation of 1900.
079   * </p>
080   * <p>
081   * The depth is calculated using the equation: (minimumDepthInMeters + maximumDepthInMeters) / 2.
082   * For consistency and ease of use GBIF decided to always use a value in meters plus it's accurracy instead of
083   * min/max values which are sometimes used in Darwin Core. See also elevation & distanceAboveSurface.
084   * </p>
085   */
086  depth(DwcTerm.GROUP_LOCATION),
087
088  /**
089   * Depth accuracy is the uncertainty for the depth in meters.
090   * <p>
091   * The depth accuracy is calculated using the equation: (maximumDepthInMeters - minimumDepthInMeters) / 2
092   * in case a minimum and maximum verbatim value is given.
093   * </p>
094   */
095  depthAccuracy(DwcTerm.GROUP_LOCATION),
096
097  distanceAboveSurface(DwcTerm.GROUP_LOCATION),
098  distanceAboveSurfaceAccuracy(DwcTerm.GROUP_LOCATION),
099
100  /**
101   * Any issue found during processing and interpretation or the record.
102   * See <a href="http://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/OccurrenceIssue.html">OccurrenceIssue enumeration</a> for possible values.
103   */
104  issue(DwcTerm.GROUP_OCCURRENCE),
105
106  /**
107   * The media type given as Dublin Core type values, in particular StillImage, MovingImage or Sound.
108   */
109  mediaType(DwcTerm.GROUP_OCCURRENCE),
110  // experimental Occurrence properties
111  verbatimLabel(DwcTerm.GROUP_OCCURRENCE),
112  infraspecificMarker(DwcTerm.GROUP_OCCURRENCE),
113  // Types and Specimen checklist extension
114  typeDesignatedBy(DwcTerm.GROUP_OCCURRENCE),
115  typeDesignationType(DwcTerm.GROUP_OCCURRENCE),
116
117  /**
118   * Boolean indicating that a valid latitude and longitude exists.
119   * Even if existing it might still have issues, see hasGeospatialIssues and issue.
120   */
121  hasCoordinate(DwcTerm.GROUP_OCCURRENCE),
122
123  /**
124   * Boolean indicating that some spatial validation rule has not passed.
125   * Primarily used to indicate that the record should not be displayed on a map.
126   */
127  hasGeospatialIssues(DwcTerm.GROUP_OCCURRENCE),
128
129  /**
130   * The GBIF backbone key.
131   * <p>
132   * The best matching, accepted GBIF backbone name usage representing this occurrence.
133   * In case the verbatim scientific name and its classification can only be matched to a higher rank this will
134   * represent the lowest matching rank. In the worst case this could just be for example Animalia.
135   * </p>
136   * <p>
137   * In contrast dwc:taxonID is only used for the source ids similar to occurrenceID
138   * </p>
139   */
140  taxonKey(DwcTerm.GROUP_TAXON),
141
142
143  /**
144   * The GBIF backbone key of the accepted taxon key.
145   */
146  acceptedTaxonKey(DwcTerm.GROUP_TAXON),
147
148  /**
149   * The key to the accepted kingdom in the GBIF backbone.
150   */
151  kingdomKey(DwcTerm.GROUP_TAXON),
152
153  /**
154   * The key to the accepted phylum in the GBIF backbone.
155   */
156  phylumKey(DwcTerm.GROUP_TAXON),
157
158  /**
159   * The key to the accepted class in the GBIF backbone.
160   */
161  classKey(DwcTerm.GROUP_TAXON),
162
163  /**
164   * The key to the accepted order in the GBIF backbone.
165   */
166  orderKey(DwcTerm.GROUP_TAXON),
167
168  /**
169   * The key to the accepted family in the GBIF backbone.
170   */
171  familyKey(DwcTerm.GROUP_TAXON),
172
173  /**
174   * The key to the accepted genus in the GBIF backbone.
175   */
176  genusKey(DwcTerm.GROUP_TAXON),
177
178  /**
179   * The key to the accepted subgenus in the GBIF backbone.
180   */
181  subgenusKey(DwcTerm.GROUP_TAXON),
182
183  /**
184   * The backbone key to the accepted species.
185   * In case the taxonKey is of a higher rank than species (e.g. genus) speciesKey is null.
186   * In case taxonKey represents an infraspecific taxon the speciesKey points to the species
187   * the infraspecies is classified as. In case of taxonKey being a species the speciesKey is the same.
188   */
189  speciesKey(DwcTerm.GROUP_TAXON),
190
191  /**
192   * The canonical name without authorship of the accepted species.
193   */
194  species(DwcTerm.GROUP_TAXON),
195  // experimental Taxon properties
196  canonicalName(DwcTerm.GROUP_TAXON),
197  nameType(DwcTerm.GROUP_TAXON),
198
199  /**
200   * The genus part of the scientific name.
201   * <p>
202   * If the scientific name is considered to be a synonym dwc:genus refers to the accepted genus, not to the
203   * genus part of the synonym. This genericName always holds the genus part of the name no matter its classification
204   * or taxonomic status.
205   * Term proposed in Darwin Core, but not yet ratified.
206   * </p>
207   */
208  genericName(DwcTerm.GROUP_TAXON),
209
210  /**
211   * The scientific name the type associated acceptedNubKey.
212   */
213  acceptedScientificName(DwcTerm.GROUP_TAXON),
214
215  /**
216   * Scientific name as provided by the source.
217   */
218  verbatimScientificName(DwcTerm.GROUP_TAXON),
219
220  /**
221   * The scientific name the type status of this specimen applies to.
222   * Term proposed in Darwin Core, but not yet ratified.
223   */
224  typifiedName(DwcTerm.GROUP_IDENTIFICATION),
225
226  /**
227   * The kind of protocol used when the record was last crawled by GBIF.
228   * See <a href="http://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/EndpointType.html">EndpointType enumeration</a> for possible values.
229   */
230  protocol(GbifTerm.GROUP_CRAWLING),
231
232  /**
233   * The date this record was last parsed from raw xml/json into a verbatim GBIF record.
234   */
235  lastParsed(GbifTerm.GROUP_CRAWLING),
236
237  /**
238   * The date this record was last crawled/harvested by GBIF from the endpoint.
239   */
240  lastCrawled(GbifTerm.GROUP_CRAWLING),
241
242  // Species Profile checklist extension
243  isMarine(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
244  isTerrestrial(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
245  isFreshwater(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
246  isHybrid(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
247  isExtinct(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
248  livingPeriod(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "timePeriod"),
249  lifeForm(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
250  ageInDays(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
251  sizeInMillimeter(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
252  massInGram(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "weightInGram"),
253
254  // Vernacular Name checklist extension
255  organismPart(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
256  isPlural(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
257  isPreferredName(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
258
259  // Distribution checklist extension
260  appendixCITES(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
261  numberOfOccurrences(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
262
263  /**
264   * Boolean indicating if the publishing country is different
265   */
266  repatriated(DwcTerm.GROUP_OCCURRENCE),
267
268  // Calculated relative organism quantity, based on organism and sample measure types
269  relativeOrganismQuantity(DwcTerm.GROUP_MATERIAL_SAMPLE),
270
271  // To support user identifiers, like ORCID and WIKIDATA and etc.
272  recordedByID(DwcTerm.GROUP_OCCURRENCE),
273  identifiedByID(DwcTerm.GROUP_IDENTIFICATION);
274
275  private static final String PREFIX = "gbif";
276  private static final String NS = "http://rs.gbif.org/terms/1.0/";
277  private static final URI NS_URI = URI.create(NS);
278
279  public static final String GROUP_CRAWLING = "Crawling";
280  public static final String GROUP_DATASET = "Dataset";
281  public static final String GROUP_ROW_TYPE = "RowType";
282  public static final String GROUP_SPECIES_DISTRIBUTION_EXTENSION = "SpeciesDistribution";
283  public static final String GROUP_SPECIES_PROFILE_EXTENSION = "SpeciesProfile";
284  public static final String GROUP_VERNACULAR_NAME_EXTENSION = "VernacularName";
285
286  /**
287   * Lists all GBIF term groups.
288   */
289  public static final String[] GROUPS = {GROUP_CRAWLING, GROUP_DATASET, DwcTerm.GROUP_OCCURRENCE, GROUP_ROW_TYPE,
290    GROUP_SPECIES_DISTRIBUTION_EXTENSION, GROUP_SPECIES_PROFILE_EXTENSION, DwcTerm.GROUP_TAXON,
291    GROUP_VERNACULAR_NAME_EXTENSION, DwcTerm.GROUP_LOCATION};
292
293  /**
294   * Lists all GBIF terms in taxon group.
295   */
296  public static final GbifTerm[] TAXONOMIC_TERMS =
297  {GbifTerm.taxonKey, GbifTerm.acceptedTaxonKey, GbifTerm.kingdomKey, GbifTerm.phylumKey, GbifTerm.classKey,
298   GbifTerm.orderKey, GbifTerm.familyKey, GbifTerm.genusKey, GbifTerm.subgenusKey, GbifTerm.speciesKey,
299   GbifTerm.species, GbifTerm.canonicalName, GbifTerm.nameType, GbifTerm.genericName, GbifTerm.acceptedScientificName,
300   GbifTerm.verbatimScientificName};
301
302  private final String groupName;
303  private final boolean isDeprecated;
304  public final String[] normAlts;
305
306  GbifTerm(String groupName, String... alternatives) {
307    this.groupName = groupName;
308    this.normAlts = alternatives;
309    boolean deprecatedAnnotationPresent = false;
310    try {
311      deprecatedAnnotationPresent = GbifTerm.class.getField(this.name()).isAnnotationPresent(Deprecated.class);
312    } catch (NoSuchFieldException ignore) { }
313    this.isDeprecated = deprecatedAnnotationPresent;
314  }
315
316  /**
317   * The simple term name without a namespace.
318   * For example taxonKey.
319   *
320   * @return simple term name
321   */
322  @Override
323  public String simpleName() {
324    return name();
325  }
326
327  /**
328   * Array of alternative simple names in use for the term.
329   *
330   * @return simple term name
331   */
332  @Override
333  public String[] alternativeNames() {
334    return normAlts;
335  }
336
337  /**
338   * The optional group the term is grouped in.
339   * For example Occurrence, Taxon, etc.
340   */
341  public String getGroup() {
342    return groupName;
343  }
344
345
346  /**
347   * List all terms that belong to a given group.
348   *
349   * @param group the group to list terms for
350   * @return the list of GBIF terms in the given group
351   */
352  public static List<GbifTerm> listByGroup(String group) {
353    List<GbifTerm> terms = new ArrayList<GbifTerm>();
354    for (GbifTerm t : GbifTerm.values()) {
355      if (t.getGroup().equalsIgnoreCase(group)) {
356        terms.add(t);
357      }
358    }
359    return terms;
360  }
361
362  @Override
363  public String toString() {
364    return prefixedName();
365  }
366
367  @Override
368  public boolean isClass() {
369    return Character.isUpperCase(simpleName().charAt(0));
370  }
371
372  @Override
373  public String prefix() {
374    return PREFIX;
375  }
376
377  @Override
378  public URI namespace() {
379    return NS_URI;
380  }
381
382  /**
383   *
384   * @return true if the Term is annotated with @Deprecated.
385   */
386  public boolean isDeprecated(){
387    return isDeprecated;
388  }
389
390}