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   * The scientific name the type status of this specimen applies to.
217   * Term proposed in Darwin Core, but not yet ratified.
218   */
219  typifiedName(DwcTerm.GROUP_IDENTIFICATION),
220
221  /**
222   * The kind of protocol used when the record was last crawled by GBIF.
223   * See <a href="http://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/EndpointType.html">EndpointType enumeration</a> for possible values.
224   */
225  protocol(GbifTerm.GROUP_CRAWLING),
226
227  /**
228   * The date this record was last parsed from raw xml/json into a verbatim GBIF record.
229   */
230  lastParsed(GbifTerm.GROUP_CRAWLING),
231
232  /**
233   * The date this record was last crawled/harvested by GBIF from the endpoint.
234   */
235  lastCrawled(GbifTerm.GROUP_CRAWLING),
236
237  // Species Profile checklist extension
238  isMarine(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
239  isTerrestrial(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
240  isFreshwater(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
241  isHybrid(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
242  isExtinct(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
243  livingPeriod(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "timePeriod"),
244  lifeForm(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
245  ageInDays(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
246  sizeInMillimeter(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION),
247  massInGram(GbifTerm.GROUP_SPECIES_PROFILE_EXTENSION, "weightInGram"),
248
249  // Vernacular Name checklist extension
250  organismPart(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
251  isPlural(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
252  isPreferredName(GbifTerm.GROUP_VERNACULAR_NAME_EXTENSION),
253
254  // Distribution checklist extension
255  appendixCITES(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
256  numberOfOccurrences(GbifTerm.GROUP_SPECIES_DISTRIBUTION_EXTENSION),
257
258  /**
259   * Boolean indicating if the publishing country is different
260   */
261  repatriated(DwcTerm.GROUP_OCCURRENCE);
262
263  private static final String PREFIX = "gbif";
264  private static final String NS = "http://rs.gbif.org/terms/1.0/";
265  private static final URI NS_URI = URI.create(NS);
266
267  public static final String GROUP_CRAWLING = "Crawling";
268  public static final String GROUP_DATASET = "Dataset";
269  public static final String GROUP_ROW_TYPE = "RowType";
270  public static final String GROUP_SPECIES_DISTRIBUTION_EXTENSION = "SpeciesDistribution";
271  public static final String GROUP_SPECIES_PROFILE_EXTENSION = "SpeciesProfile";
272  public static final String GROUP_VERNACULAR_NAME_EXTENSION = "VernacularName";
273
274  /**
275   * Lists all GBIF term groups.
276   */
277  public static final String[] GROUPS = {GROUP_CRAWLING, GROUP_DATASET, DwcTerm.GROUP_OCCURRENCE, GROUP_ROW_TYPE,
278    GROUP_SPECIES_DISTRIBUTION_EXTENSION, GROUP_SPECIES_PROFILE_EXTENSION, DwcTerm.GROUP_TAXON,
279    GROUP_VERNACULAR_NAME_EXTENSION, DwcTerm.GROUP_LOCATION};
280
281  /**
282   * Lists all GBIF terms in taxon group.
283   */
284  public static final GbifTerm[] TAXONOMIC_TERMS =
285  {GbifTerm.taxonKey, GbifTerm.acceptedTaxonKey, GbifTerm.kingdomKey, GbifTerm.phylumKey, GbifTerm.classKey,
286   GbifTerm.orderKey, GbifTerm.familyKey, GbifTerm.genusKey, GbifTerm.subgenusKey, GbifTerm.speciesKey,
287   GbifTerm.species, GbifTerm.canonicalName, GbifTerm.nameType, GbifTerm.genericName, GbifTerm.acceptedScientificName};
288
289  private final String groupName;
290  private final boolean isDeprecated;
291  public final String[] normAlts;
292
293  GbifTerm(String groupName, String... alternatives) {
294    this.groupName = groupName;
295    this.normAlts = alternatives;
296    boolean deprecatedAnnotationPresent = false;
297    try {
298      deprecatedAnnotationPresent = GbifTerm.class.getField(this.name()).isAnnotationPresent(Deprecated.class);
299    } catch (NoSuchFieldException ignore) { }
300    this.isDeprecated = deprecatedAnnotationPresent;
301  }
302
303  /**
304   * The simple term name without a namespace.
305   * For example taxonKey.
306   *
307   * @return simple term name
308   */
309  @Override
310  public String simpleName() {
311    return name();
312  }
313
314  /**
315   * Array of alternative simple names in use for the term.
316   *
317   * @return simple term name
318   */
319  @Override
320  public String[] alternativeNames() {
321    return normAlts;
322  }
323
324  /**
325   * The optional group the term is grouped in.
326   * For example Occurrence, Taxon, etc.
327   */
328  public String getGroup() {
329    return groupName;
330  }
331
332
333  /**
334   * List all terms that belong to a given group.
335   *
336   * @param group the group to list terms for
337   * @return the list of GBIF terms in the given group
338   */
339  public static List<GbifTerm> listByGroup(String group) {
340    List<GbifTerm> terms = new ArrayList<GbifTerm>();
341    for (GbifTerm t : GbifTerm.values()) {
342      if (t.getGroup().equalsIgnoreCase(group)) {
343        terms.add(t);
344      }
345    }
346    return terms;
347  }
348
349  @Override
350  public String toString() {
351    return prefixedName();
352  }
353
354  @Override
355  public boolean isClass() {
356    return Character.isUpperCase(simpleName().charAt(0));
357  }
358
359  @Override
360  public String prefix() {
361    return PREFIX;
362  }
363
364  @Override
365  public URI namespace() {
366    return NS_URI;
367  }
368
369  /**
370   *
371   * @return true if the Term is annotated with @Deprecated.
372   */
373  public boolean isDeprecated(){
374    return isDeprecated;
375  }
376
377}