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