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