001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.model.occurrence; 015 016import org.gbif.api.annotation.Experimental; 017import org.gbif.api.model.common.Identifier; 018import org.gbif.api.model.common.LinneanClassification; 019import org.gbif.api.model.common.LinneanClassificationKeys; 020import org.gbif.api.model.common.MediaObject; 021import org.gbif.api.util.ClassificationUtils; 022import org.gbif.api.util.IsoDateInterval; 023import org.gbif.api.vocabulary.BasisOfRecord; 024import org.gbif.api.vocabulary.Continent; 025import org.gbif.api.vocabulary.Country; 026import org.gbif.api.vocabulary.GbifRegion; 027import org.gbif.api.vocabulary.License; 028import org.gbif.api.vocabulary.OccurrenceIssue; 029import org.gbif.api.vocabulary.OccurrenceStatus; 030import org.gbif.api.vocabulary.Rank; 031import org.gbif.api.vocabulary.Sex; 032import org.gbif.api.vocabulary.TaxonomicStatus; 033import org.gbif.dwc.terms.DwcTerm; 034import org.gbif.dwc.terms.GbifTerm; 035import org.gbif.dwc.terms.Term; 036import org.gbif.dwc.terms.UnknownTerm; 037 038import java.lang.reflect.Field; 039import java.lang.reflect.Modifier; 040import java.net.URI; 041import java.util.ArrayList; 042import java.util.Arrays; 043import java.util.Collections; 044import java.util.Date; 045import java.util.EnumSet; 046import java.util.HashMap; 047import java.util.List; 048import java.util.Map; 049import java.util.Objects; 050import java.util.Optional; 051import java.util.Set; 052import java.util.stream.Collectors; 053import java.util.stream.Stream; 054 055import javax.annotation.Nullable; 056import javax.validation.constraints.Max; 057import javax.validation.constraints.Min; 058import javax.validation.constraints.NotNull; 059 060import com.fasterxml.jackson.annotation.JsonAnyGetter; 061import com.fasterxml.jackson.annotation.JsonIgnore; 062import com.fasterxml.jackson.annotation.JsonProperty; 063import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 064import com.fasterxml.jackson.databind.annotation.JsonSerialize; 065 066import io.swagger.v3.oas.annotations.ExternalDocumentation; 067import io.swagger.v3.oas.annotations.media.Schema; 068import lombok.EqualsAndHashCode; 069import lombok.ToString; 070 071/** 072 * Represents an Occurrence as interpreted by GBIF, adding typed properties on top of the verbatim ones. 073 */ 074@EqualsAndHashCode 075@ToString 076@SuppressWarnings("unused") 077public class Occurrence extends VerbatimOccurrence implements LinneanClassification, LinneanClassificationKeys { 078 079 public static final String GEO_DATUM = "WGS84"; 080 // keep names of ALL properties of this class in a set for jackson serialization, see #properties() 081 private static final Set<String> PROPERTIES = Collections.unmodifiableSet( 082 Stream.concat( 083 // we need to these JSON properties manually because we have a fixed getter but no field for it 084 Stream.of(DwcTerm.geodeticDatum.simpleName(), "class", DwcTerm.countryCode.simpleName(), GbifTerm.gbifRegion.simpleName(), GbifTerm.publishedByGbifRegion.simpleName()), 085 Stream.concat(Arrays.stream(Occurrence.class.getDeclaredFields()), 086 Arrays.stream(VerbatimOccurrence.class.getDeclaredFields())) 087 .filter(field -> !Modifier.isStatic(field.getModifiers())) 088 .map(Field::getName)).collect(Collectors.toSet())); 089 090 // occurrence fields 091 092 // OpenAPI documentation comes from the enumeration. 093 private BasisOfRecord basisOfRecord; 094 095 @Schema( 096 description = "The number of individuals present at the time of the Occurrence.", 097 externalDocs = @ExternalDocumentation( 098 description = "Darwin Core definition", 099 url = "https://rs.tdwg.org/dwc/terms/individualCount" 100 ) 101 ) 102 private Integer individualCount; 103 104 // OpenAPI documentation comes from the enumeration. 105 private OccurrenceStatus occurrenceStatus; 106 107 // OpenAPI documentation comes from the enumeration. 108 private Sex sex; 109 110 @Schema( 111 description = "The age class or life stage of the Organism(s) at the time the Occurrence was recorded.\n\n" + 112 "Values are aligned to the [GBIF LifeStage vocabulary](https://registry.gbif.org/vocabulary/LifeStage/concepts)", 113 externalDocs = @ExternalDocumentation( 114 description = "Darwin Core definition", 115 url = "https://rs.tdwg.org/dwc/terms/lifeStage" 116 ) 117 ) 118 private String lifeStage; 119 120 @Schema( 121 description = "Statement about whether an organism or organisms have been introduced to a given place and time " + 122 "through the direct or indirect activity of modern humans.\n\n" + 123 "Values are aligned to the [GBIF EstablishmentMeans vocabulary](https://registry.gbif.org/vocabulary/EstablishmentMeans/concepts)," + 124 "which is derived from the [Darwin Core EstablishmentMeans vocabulary](https://dwc.tdwg.org/em/).", 125 externalDocs = @ExternalDocumentation( 126 description = "Darwin Core definition", 127 url = "https://rs.tdwg.org/dwc/terms/establishmentMeans" 128 ) 129 ) 130 private String establishmentMeans; 131 132 @Schema( 133 description = "The degree to which an Organism survives, reproduces, and expands its range at the given " + 134 "place and time.\n\n" + 135 "Values are aligned to the [GBIF DegreeOfEstablishment vocabulary](https://registry.gbif.org/vocabulary/DegreeOfEstablishment/concepts)," + 136 "which is derived from the [Darwin Core DegreeOfEstablishment vocabulary](https://dwc.tdwg.org/doe/).", 137 externalDocs = @ExternalDocumentation( 138 description = "Darwin Core definition", 139 url = "https://rs.tdwg.org/dwc/terms/degreeOfEstablishment" 140 ) 141 ) 142 private String degreeOfEstablishment; 143 144 @Schema( 145 description = "The process by which an Organism came to be in a given place at a given time.\n\n" + 146 "Values are aligned to the [GBIF Pathway vocabulary](https://registry.gbif.org/vocabulary/Pathway/concepts)," + 147 "which is derived from the [Darwin Core Pathway vocabulary](https://dwc.tdwg.org/pw/).", 148 externalDocs = @ExternalDocumentation( 149 description = "Darwin Core definition", 150 url = "https://rs.tdwg.org/dwc/terms/pathway" 151 ) 152 ) 153 private String pathway; 154 155 // taxonomy as NUB keys → LinneanClassificationKeys 156 157 @Schema( 158 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the most specific " + 159 "(lowest rank) taxon for this occurrence. This could be a synonym, see `acceptedTaxonKey`.", 160 externalDocs = @ExternalDocumentation( 161 description = "Darwin Core definition", 162 url = "https://rs.tdwg.org/dwc/terms/" 163 ) 164 ) 165 private Integer taxonKey; 166 167 @Schema( 168 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the kingdom of this" + 169 "occurrence.", 170 externalDocs = @ExternalDocumentation( 171 description = "Darwin Core definition", 172 url = "https://rs.tdwg.org/dwc/terms/" 173 ) 174 ) 175 private Integer kingdomKey; 176 177 @Schema( 178 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the phylum of this" + 179 "occurrence.", 180 externalDocs = @ExternalDocumentation( 181 description = "Darwin Core definition", 182 url = "https://rs.tdwg.org/dwc/terms/" 183 ) 184 ) 185 private Integer phylumKey; 186 187 @Schema( 188 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the class of this" + 189 "occurrence.", 190 externalDocs = @ExternalDocumentation( 191 description = "Darwin Core definition", 192 url = "https://rs.tdwg.org/dwc/terms/" 193 ) 194 ) 195 private Integer classKey; 196 197 @Schema( 198 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the order of this" + 199 "occurrence.", 200 externalDocs = @ExternalDocumentation( 201 description = "Darwin Core definition", 202 url = "https://rs.tdwg.org/dwc/terms/" 203 ) 204 ) 205 private Integer orderKey; 206 207 @Schema( 208 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the family of this" + 209 "occurrence.", 210 externalDocs = @ExternalDocumentation( 211 description = "Darwin Core definition", 212 url = "https://rs.tdwg.org/dwc/terms/" 213 ) 214 ) 215 private Integer familyKey; 216 217 @Schema( 218 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the genus of this" + 219 "occurrence.", 220 externalDocs = @ExternalDocumentation( 221 description = "Darwin Core definition", 222 url = "https://rs.tdwg.org/dwc/terms/" 223 ) 224 ) 225 private Integer genusKey; 226 227 @Schema( 228 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the subgenus of this" + 229 "occurrence.", 230 externalDocs = @ExternalDocumentation( 231 description = "Darwin Core definition", 232 url = "https://rs.tdwg.org/dwc/terms/" 233 ) 234 ) 235 private Integer subgenusKey; 236 237 @Schema( 238 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the species of this" + 239 "occurrence.", 240 externalDocs = @ExternalDocumentation( 241 description = "Darwin Core definition", 242 url = "https://rs.tdwg.org/dwc/terms/" 243 ) 244 ) 245 private Integer speciesKey; 246 247 @Schema( 248 description = "A taxon key from the [GBIF backbone](https://doi.org/10.15468/39omei) for the accepted taxon of " + 249 "this occurrence.", 250 externalDocs = @ExternalDocumentation( 251 description = "Darwin Core definition", 252 url = "https://rs.tdwg.org/dwc/terms/" 253 ) 254 ) 255 private Integer acceptedTaxonKey; 256 257 // taxonomy as name strings → LinneanClassification 258 259 @Schema( 260 description = "The scientific name (including authorship) for the taxon from the " + 261 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence. This could be a synonym, see " + 262 "also `acceptedScientificName`.", 263 externalDocs = @ExternalDocumentation( 264 description = "Darwin Core definition", 265 url = "https://rs.tdwg.org/dwc/terms/" 266 ) 267 ) 268 private String scientificName; // the interpreted name matching taxonKey 269 270 @Schema( 271 description = "The accepted scientific name (including authorship) for the taxon from the " + 272 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 273 externalDocs = @ExternalDocumentation( 274 description = "Darwin Core definition", 275 url = "https://rs.tdwg.org/dwc/terms/" 276 ) 277 ) 278 private String acceptedScientificName; 279 280 @Schema( 281 description = "The kingdom name (excluding authorship) for the kingdom from the " + 282 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 283 externalDocs = @ExternalDocumentation( 284 description = "Darwin Core definition", 285 url = "https://rs.tdwg.org/dwc/terms/" 286 ) 287 ) 288 private String kingdom; 289 290 @Schema( 291 description = "The phylum name (excluding authorship) for the phylum from the " + 292 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 293 externalDocs = @ExternalDocumentation( 294 description = "Darwin Core definition", 295 url = "https://rs.tdwg.org/dwc/terms/" 296 ) 297 ) 298 private String phylum; 299 300 @Schema( 301 description = "The class name (excluding authorship) for the class from the " + 302 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 303 externalDocs = @ExternalDocumentation( 304 description = "Darwin Core definition", 305 url = "https://rs.tdwg.org/dwc/terms/" 306 ) 307 ) 308 @JsonProperty("class") 309 private String clazz; 310 311 @Schema( 312 description = "The order name (excluding authorship) for the order from the " + 313 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 314 externalDocs = @ExternalDocumentation( 315 description = "Darwin Core definition", 316 url = "https://rs.tdwg.org/dwc/terms/" 317 ) 318 ) 319 private String order; 320 321 @Schema( 322 description = "The family name (excluding authorship) for the family from the " + 323 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 324 externalDocs = @ExternalDocumentation( 325 description = "Darwin Core definition", 326 url = "https://rs.tdwg.org/dwc/terms/" 327 ) 328 ) 329 private String family; 330 331 @Schema( 332 description = "The genus name (excluding authorship) for the genus from the " + 333 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 334 externalDocs = @ExternalDocumentation( 335 description = "Darwin Core definition", 336 url = "https://rs.tdwg.org/dwc/terms/" 337 ) 338 ) 339 private String genus; 340 341 @Schema( 342 description = "The subgenus name (excluding authorship) for the subgenus from the " + 343 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 344 externalDocs = @ExternalDocumentation( 345 description = "Darwin Core definition", 346 url = "https://rs.tdwg.org/dwc/terms/" 347 ) 348 ) 349 private String subgenus; 350 351 @Schema( 352 description = "The species name (excluding authorship) for the species from the " + 353 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 354 externalDocs = @ExternalDocumentation( 355 description = "Darwin Core definition", 356 url = "https://rs.tdwg.org/dwc/terms/" 357 ) 358 ) 359 private String species; 360 361 // atomised scientific name 362 363 @Schema( 364 description = "The genus name part of the species name from the " + 365 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 366 externalDocs = @ExternalDocumentation( 367 description = "Darwin Core definition", 368 url = "https://rs.tdwg.org/dwc/terms/genericName" 369 ) 370 ) 371 private String genericName; 372 373 @Schema( 374 description = "The specific name part of the species name from the " + 375 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 376 externalDocs = @ExternalDocumentation( 377 description = "Darwin Core definition", 378 url = "https://rs.tdwg.org/dwc/terms/specificEpithet" 379 ) 380 ) 381 private String specificEpithet; 382 383 @Schema( 384 description = "The infraspecific name part of the species name from the " + 385 "[GBIF backbone](https://doi.org/10.15468/39omei) matched to this occurrence.", 386 externalDocs = @ExternalDocumentation( 387 description = "Darwin Core definition", 388 url = "https://rs.tdwg.org/dwc/terms/infraspecificEpithet" 389 ) 390 ) 391 private String infraspecificEpithet; 392 393 @Schema( 394 description = "The taxonomic rank of the most specific name in the scientificName.", 395 externalDocs = @ExternalDocumentation( 396 description = "Darwin Core definition", 397 url = "https://rs.tdwg.org/dwc/terms/taxonRank" 398 ) 399 ) 400 private Rank taxonRank; 401 402 @Schema( 403 description = "The status of the use of the scientificName as a label for a taxon.", 404 externalDocs = @ExternalDocumentation( 405 description = "Darwin Core definition", 406 url = "https://rs.tdwg.org/dwc/terms/taxonomicStatus" 407 ) 408 ) 409 private TaxonomicStatus taxonomicStatus; 410 411 @Schema( 412 description = "The IUCN Red List Category of the taxon of this occurrence.\n\n" + 413 "See the [GBIF vocabulary](https://rs.gbif.org/vocabulary/iucn/threat_status/) for the values and their " + 414 "definitions, and the [IUCN Red List of Threatened Species dataset in GBIF](https://doi.org/10.15468/0qnb58) " + 415 "for the version of the Red List GBIF's interpretation procedures are using.", 416 externalDocs = @ExternalDocumentation( 417 description = "GBIF vocabulary", 418 url = "https://rs.gbif.org/vocabulary/iucn/threat_status/" 419 ) 420 ) 421 private String iucnRedListCategory; 422 423 // identification 424 425 @Schema( 426 description = "The date on which the subject was determined as representing the Taxon.", 427 externalDocs = @ExternalDocumentation( 428 description = "Darwin Core definition", 429 url = "https://rs.tdwg.org/dwc/terms/dateIdentified" 430 ) 431 ) 432 private Date dateIdentified; 433 434 // location 435 436 @Schema( 437 description = "The geographic latitude (in decimal degrees, using the WGS84 datum) of the geographic centre " + 438 "of the location of the occurrence.", 439 externalDocs = @ExternalDocumentation( 440 description = "Darwin Core definition", 441 url = "https://rs.tdwg.org/dwc/terms/decimalLatitude" 442 ) 443 ) 444 private Double decimalLatitude; 445 446 @Schema( 447 description = "The geographic longitude (in decimal degrees, using the WGS84 datum) of the geographic centre " + 448 "of the location of the occurrence.", 449 externalDocs = @ExternalDocumentation( 450 description = "Darwin Core definition", 451 url = "https://rs.tdwg.org/dwc/terms/decimalLongitude" 452 ) 453 ) 454 private Double decimalLongitude; 455 456 //coordinatePrecision and coordinateUncertaintyInMeters should be BigDecimal see POR-2795 457 458 @Schema( 459 description = "A decimal representation of the precision of the coordinates given in the decimalLatitude and decimalLongitude.", 460 externalDocs = @ExternalDocumentation( 461 description = "Darwin Core definition", 462 url = "https://rs.tdwg.org/dwc/terms/coordinatePrecision" 463 ) 464 ) 465 private Double coordinatePrecision; 466 467 @Schema( 468 description = "The horizontal distance (in metres) from the given decimalLatitude and decimalLongitude " + 469 "describing the smallest circle containing the whole of the Location.", 470 externalDocs = @ExternalDocumentation( 471 description = "Darwin Core definition", 472 url = "https://rs.tdwg.org/dwc/terms/coordinateUncertaintyInMeters" 473 ) 474 ) 475 private Double coordinateUncertaintyInMeters; 476 477 @Schema( 478 description = "**Deprecated.** This value is always null. It is an obsolete Darwin Core term.", 479 externalDocs = @ExternalDocumentation( 480 description = "Darwin Core definition", 481 url = "https://rs.tdwg.org/dwc/terms/" 482 ) 483 ) 484 @Deprecated //see getter 485 private Double coordinateAccuracy; 486 487 @Schema( 488 description = "Elevation (altitude) in metres above sea level. This is not a current Darwin Core term." 489 ) 490 private Double elevation; 491 492 @Schema( 493 description = "The value of the potential error associated with the elevation. This is not a current Darwin Core term." 494 ) 495 private Double elevationAccuracy; 496 497 @Schema( 498 description = "Depth in metres below sea level. This is not a current Darwin Core term." 499 ) 500 private Double depth; 501 502 @Schema( 503 description = "The value of the potential error associated with the depth. This is not a current Darwin Core term." 504 ) 505 private Double depthAccuracy; 506 507 // OpenAPI documentation from enumeration 508 private Continent continent; 509 510 @JsonSerialize(using = Country.IsoSerializer.class) 511 @JsonDeserialize(using = Country.IsoDeserializer.class) 512 private Country country; 513 514 @Schema( 515 description = "The name of the next-smaller administrative region than country (state, province, canton, " + 516 "department, region, etc.) in which the occurrence occurs.\n\n" + 517 "This value is unaltered by GBIF's processing; see also the GADM fields.", 518 externalDocs = @ExternalDocumentation( 519 description = "Darwin Core definition", 520 url = "https://rs.tdwg.org/dwc/terms/stateProvince" 521 ) 522 ) 523 private String stateProvince; 524 525 @Schema( 526 description = "The administrative divisions according to the [GADM database](https://gadm.org/).\n\n" + 527 "This value is applied by GBIF's processing without consideration of the `stateProvince`, `county` or `locality` fields." 528 ) 529 private Gadm gadm = new Gadm(); 530 531 @Schema( 532 description = "The name of the water body in which the Location occurs.", 533 externalDocs = @ExternalDocumentation( 534 description = "Darwin Core definition", 535 url = "https://rs.tdwg.org/dwc/terms/waterBody" 536 ) 537 ) 538 private String waterBody; 539 540 @Schema( 541 description = "The distance in metres of the occurrence from a centroid known to be applied to occurrences " + 542 "during georeferencing. This can potentially indicate low-precision georeferencing, check the values of " + 543 "`coordinateUncertaintyInMeters` and `georeferenceRemarks`." 544 ) 545 private Double distanceFromCentroidInMeters; 546 547 @Schema( 548 description = "A list (concatenated and separated) of geographic names less specific than the information captured in the dwc:locality term.", 549 externalDocs = @ExternalDocumentation( 550 description = "Darwin Core definition", 551 url = "https://rs.tdwg.org/dwc/terms/higherGeography" 552 ) 553 ) 554 private String higherGeography; 555 556 @Schema( 557 description = "A list (concatenated and separated) of names of people, groups, or organizations who determined the georeference (spatial representation) for the dcterms:Location.", 558 externalDocs = @ExternalDocumentation( 559 description = "Darwin Core definition", 560 url = "https://rs.tdwg.org/dwc/terms/georeferencedBy" 561 ) 562 ) 563 private String georeferencedBy; 564 565 // recording event 566 567 @Schema( 568 description = "The four-digit year in which the event occurred, according to the Common Era calendar.", 569 externalDocs = @ExternalDocumentation( 570 description = "Darwin Core definition", 571 url = "https://rs.tdwg.org/dwc/terms/year" 572 ) 573 ) 574 private Integer year; 575 576 @Schema( 577 description = "The integer month in which the Event occurred.", 578 externalDocs = @ExternalDocumentation( 579 description = "Darwin Core definition", 580 url = "https://rs.tdwg.org/dwc/terms/month" 581 ) 582 ) 583 private Integer month; 584 585 @Schema( 586 description = "The integer day of the month on which the Event occurred.", 587 externalDocs = @ExternalDocumentation( 588 description = "Darwin Core definition", 589 url = "https://rs.tdwg.org/dwc/terms/day" 590 ) 591 ) 592 private Integer day; 593 594 @Schema( 595 description = "The date-time during which an Event occurred. For occurrences, this is the date-time when the " + 596 "event was recorded. Not suitable for a time in a geological context.", 597 externalDocs = @ExternalDocumentation( 598 description = "Darwin Core definition", 599 url = "https://rs.tdwg.org/dwc/terms/eventDate" 600 ) 601 ) 602 private IsoDateInterval eventDate; 603 604 @Schema( 605 description = "The latest integer day of the year on which the Event occurred (1 for 1 January, 365 for " + 606 "31 December, except in a leap year, in which case it is 366).", 607 externalDocs = @ExternalDocumentation( 608 description = "Darwin Core definition", 609 url = "https://rs.tdwg.org/dwc/terms/endDayOfYear" 610 ) 611 ) 612 private Integer startDayOfYear; 613 614 @Schema( 615 description = "The earliest integer day of the year on which the Event occurred (1 for 1 January, 365 for " + 616 "31 December, except in a leap year, in which case it is 366).", 617 externalDocs = @ExternalDocumentation( 618 description = "Darwin Core definition", 619 url = "https://rs.tdwg.org/dwc/terms/startDayOfYear" 620 ) 621 ) 622 private Integer endDayOfYear; 623 624 @Schema( 625 description = "A list (concatenated and separated) of nomenclatural types (type status, typified scientific name, " + 626 "publication) applied to the occurrence.", 627 externalDocs = @ExternalDocumentation( 628 description = "Darwin Core definition", 629 url = "https://rs.tdwg.org/dwc/terms/typeStatus" 630 ) 631 ) 632 private String typeStatus; 633 634 // extracted from type status, but we should propose a new dwc term for this! 635 // for example: "Paratype of Taeniopteryx metequi Ricker & Ross" is status=Paratype, typifiedName=Taeniopteryx metequi Ricker & Ross 636 @Schema( 637 description = "The scientific name that is based on the type specimen.\n\n" + 638 "This is not yet a Darwin Core term, see the [proposal to add it](https://github.com/tdwg/dwc/issues/28)." 639 ) 640 private String typifiedName; // missing from DwC 641 642 @Schema( 643 description = "A specific interpretation issue found during processing and interpretation of the record.\n\n" + 644 "See the https://links.gbif.org/occurrence-issues[list of occurrence issues] and the " + 645 "https://gbif.github.io/gbif-api/apidocs/org/gbif/api/vocabulary/OccurrenceIssue.html[OccurrenceIssue enumeration] " + 646 "for possible values and definitions." 647 ) 648 private Set<OccurrenceIssue> issues = EnumSet.noneOf(OccurrenceIssue.class); 649 650 // record level 651 652 @Schema( 653 description = "The most recent date-time on which the occurrence was changed, according to the publisher.", 654 externalDocs = @ExternalDocumentation( 655 description = "Dublin Core definition", 656 url = "https://purl.org/dc/terms/modified" 657 ) 658 ) 659 private Date modified; // interpreted dc:modified, i.e. date changed in source 660 661 @Schema( 662 description = "The time this occurrence was last processed by GBIF's interpretation system “Pipelines”.\n\n" + 663 "This is the time the record was last changed in GBIF, **not** the time the record was last changed by the " + 664 "publisher. Data is also reprocessed when we changed the taxonomic backbone, geographic data sources or " + 665 "other interpretation procedures.\n\n" + 666 "An earlier interpretation system distinguished between “parsing” and “interpretation”, but in the current " + 667 "system there is only one process — the two dates will always be the same." 668 ) 669 private Date lastInterpreted; 670 671 @Schema( 672 description = "A related resource that is referenced, cited, or otherwise pointed to by the described resource.", 673 externalDocs = @ExternalDocumentation( 674 description = "Dublin Core definition", 675 url = "https://purl.org/dc/terms/references" 676 ) 677 ) 678 private URI references; 679 680 @Schema( 681 description = "A legal document giving official permission to do something with the occurrence.", 682 externalDocs = @ExternalDocumentation( 683 description = "Dublin Core definition", 684 url = "https://purl.org/dc/terms/license" 685 ) 686 ) 687 private License license; 688 689 @Schema( 690 description = "A number or enumeration value for the quantity of organisms.", 691 externalDocs = @ExternalDocumentation( 692 description = "Darwin Core definition", 693 url = "https://rs.tdwg.org/dwc/terms/organismQuantity" 694 ) 695 ) 696 private Double organismQuantity; 697 698 @Schema( 699 description = "The type of quantification system used for the quantity of organisms.", 700 externalDocs = @ExternalDocumentation( 701 description = "Darwin Core definition", 702 url = "https://rs.tdwg.org/dwc/terms/organismQuantityType" 703 ) 704 ) 705 private String organismQuantityType; 706 707 @Schema( 708 description = "The unit of measurement of the size (time duration, length, area, or volume) of a sample in a sampling event.", 709 externalDocs = @ExternalDocumentation( 710 description = "Darwin Core definition", 711 url = "https://rs.tdwg.org/dwc/terms/sampleSizeUnit" 712 ) 713 ) 714 private String sampleSizeUnit; 715 716 @Schema( 717 description = "A numeric value for a measurement of the size (time duration, length, area, or volume) of a sample in a sampling event.", 718 externalDocs = @ExternalDocumentation( 719 description = "Darwin Core definition", 720 url = "https://rs.tdwg.org/dwc/terms/sampleSizeValue" 721 ) 722 ) 723 private Double sampleSizeValue; 724 725 @Schema( 726 description = "The relative measurement of the quantity of the organism (i.e. without absolute units)." 727 ) 728 private Double relativeOrganismQuantity; 729 730 @Schema( 731 description = "Flag occurrence when associatedSequences/extension exists" 732 ) 733 private boolean isSequenced; 734 735 @Schema( 736 description = "A list (concatenated and separated) of identifiers (publication, global unique identifier, URI) " 737 + "of genetic sequence information associated with the material entity.", 738 externalDocs = 739 @ExternalDocumentation( 740 description = "Darwin Core definition", 741 url = "https://rs.tdwg.org/dwc/terms/associatedSequences")) 742 private String associatedSequences; 743 744 // interpreted extension data 745 746 @Schema( 747 description = "Alternative identifiers for the occurrence.", 748 externalDocs = @ExternalDocumentation( 749 description = "GBIF Alternative Identifiers extension", 750 url = "https://rs.gbif.org/terms/1.0/Identifier" 751 ) 752 ) 753 private List<Identifier> identifiers = new ArrayList<>(); 754 755 @Schema( 756 description = "Multimedia related to te occurrence.", 757 externalDocs = @ExternalDocumentation( 758 description = "GBIF Multimedia extension", 759 url = "https://rs.gbif.org/terms/1.0/Multimedia" 760 ) 761 ) 762 private List<MediaObject> media = new ArrayList<>(); 763 764 @Schema( 765 description = "Measurements or facts about the the occurrence.", 766 externalDocs = @ExternalDocumentation( 767 description = "Darwin Core definition", 768 url = "https://rs.tdwg.org/dwc/terms/MeasurementOrFact" 769 ) 770 ) 771 private List<MeasurementOrFact> facts = new ArrayList<>(); 772 773 @Schema( 774 description = "Relationships between occurrences.", 775 externalDocs = @ExternalDocumentation( 776 description = "Darwin Core definition", 777 url = "https://rs.tdwg.org/dwc/terms/ResourceRelationship" 778 ) 779 ) 780 private List<OccurrenceRelation> relations = new ArrayList<>(); 781 782 @Schema( 783 description = "A list of the globally unique identifiers for the person, people, groups, or organizations " + 784 "responsible for recording the original Occurrence.", 785 externalDocs = @ExternalDocumentation( 786 description = "Darwin Core definition", 787 url = "https://rs.tdwg.org/dwc/terms/recordedByID" 788 ) 789 ) 790 @JsonProperty("recordedByIDs") 791 private List<AgentIdentifier> recordedByIds = new ArrayList<>(); 792 793 @Schema( 794 description = "A list of the globally unique identifiers for the person, people, groups, or organizations " + 795 "responsible for assigning the Taxon to the occurrence.", 796 externalDocs = @ExternalDocumentation( 797 description = "Darwin Core definition", 798 url = "https://rs.tdwg.org/dwc/terms/identifiedByID" 799 ) 800 ) 801 @JsonProperty("identifiedByIDs") 802 private List<AgentIdentifier> identifiedByIds = new ArrayList<>(); 803 804 @Schema( 805 description = "**Experimental.** The UUID of the institution holding the specimen occurrence, from GRSciColl." 806 ) 807 @Experimental 808 private String institutionKey; 809 810 @Schema( 811 description = "**Experimental.** The UUID of the collection containing the specimen occurrence, from GRSciColl." 812 ) 813 @Experimental 814 private String collectionKey; 815 816 @Schema( 817 description = "**Experimental.** Whether the occurrence belongs to a machine-calculated cluster of probable " + 818 "duplicate occurrences.", 819 externalDocs = @ExternalDocumentation( 820 description = "GBIF Data Blog", 821 url = "https://data-blog.gbif.org/post/clustering-occurrences/" 822 ) 823 ) 824 @Experimental 825 private boolean isInCluster; 826 827 @Schema( 828 description = "An identifier for the set of data. May be a global unique identifier or an identifier specific to " + 829 "a collection or institution.", 830 externalDocs = @ExternalDocumentation( 831 description = "Darwin Core definition", 832 url = "https://rs.tdwg.org/dwc/terms/datasetID" 833 ) 834 ) 835 private String datasetID; 836 837 @Schema( 838 description = "The name identifying the data set from which the record was derived.", 839 externalDocs = @ExternalDocumentation( 840 description = "Darwin Core definition", 841 url = "https://rs.tdwg.org/dwc/terms/" 842 ) 843 ) 844 private String datasetName; 845 846 @Schema( 847 description = "A list (concatenated and separated) of previous or alternate fully qualified catalogue numbers " + 848 "or other human-used identifiers for the same occurrence, whether in the current or any other data set or collection.", 849 externalDocs = @ExternalDocumentation( 850 description = "Darwin Core definition", 851 url = "https://rs.tdwg.org/dwc/terms/otherCatalogNumbers" 852 ) 853 ) 854 private String otherCatalogNumbers; 855 856 @Schema( 857 description = "The full name of the earliest possible geochronologic eon or lowest chrono-stratigraphic eonothem or the informal name (\"Precambrian\") attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 858 externalDocs = @ExternalDocumentation( 859 description = "Darwin Core definition", 860 url = "https://rs.tdwg.org/dwc/terms/earliestEonOrLowestEonothem" 861 ) 862 ) 863 private String earliestEonOrLowestEonothem; 864 865 @Schema( 866 description = "The full name of the latest possible geochronologic eon or highest chrono-stratigraphic eonothem or the informal name (\"Precambrian\") attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 867 externalDocs = @ExternalDocumentation( 868 description = "Darwin Core definition", 869 url = "https://rs.tdwg.org/dwc/terms/latestEonOrHighestEonothem" 870 ) 871 ) 872 private String latestEonOrHighestEonothem; 873 874 @Schema( 875 description = "The full name of the earliest possible geochronologic era or lowest chronostratigraphic erathem attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 876 externalDocs = @ExternalDocumentation( 877 description = "Darwin Core definition", 878 url = "https://rs.tdwg.org/dwc/terms/earliestEraOrLowestErathem" 879 ) 880 ) 881 private String earliestEraOrLowestErathem; 882 883 @Schema( 884 description = "The full name of the latest possible geochronologic era or highest chronostratigraphic erathem attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 885 externalDocs = @ExternalDocumentation( 886 description = "Darwin Core definition", 887 url = "https://rs.tdwg.org/dwc/terms/latestEraOrHighestErathem" 888 ) 889 ) 890 private String latestEraOrHighestErathem; 891 892 @Schema( 893 description = "The full name of the earliest possible geochronologic period or lowest chronostratigraphic system attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 894 externalDocs = @ExternalDocumentation( 895 description = "Darwin Core definition", 896 url = "https://rs.tdwg.org/dwc/terms/earliestPeriodOrLowestSystem" 897 ) 898 ) 899 private String earliestPeriodOrLowestSystem; 900 901 @Schema( 902 description = "The full name of the latest possible geochronologic period or highest chronostratigraphic system attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 903 externalDocs = @ExternalDocumentation( 904 description = "Darwin Core definition", 905 url = "https://rs.tdwg.org/dwc/terms/latestPeriodOrHighestSystem" 906 ) 907 ) 908 private String latestPeriodOrHighestSystem; 909 910 @Schema( 911 description = "The full name of the earliest possible geochronologic epoch or lowest chronostratigraphic series attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 912 externalDocs = @ExternalDocumentation( 913 description = "Darwin Core definition", 914 url = "https://rs.tdwg.org/dwc/terms/earliestEpochOrLowestSeries" 915 ) 916 ) 917 private String earliestEpochOrLowestSeries; 918 919 @Schema( 920 description = "The full name of the latest possible geochronologic epoch or highest chronostratigraphic series attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 921 externalDocs = @ExternalDocumentation( 922 description = "Darwin Core definition", 923 url = "https://rs.tdwg.org/dwc/terms/latestEpochOrHighestSeries" 924 ) 925 ) 926 private String latestEpochOrHighestSeries; 927 928 @Schema( 929 description = "The full name of the earliest possible geochronologic age or lowest chronostratigraphic stage attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 930 externalDocs = @ExternalDocumentation( 931 description = "Darwin Core definition", 932 url = "https://rs.tdwg.org/dwc/terms/earliestAgeOrLowestStage" 933 ) 934 ) 935 private String earliestAgeOrLowestStage; 936 937 @Schema( 938 description = "The full name of the latest possible geochronologic age or highest chronostratigraphic stage attributable to the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 939 externalDocs = @ExternalDocumentation( 940 description = "Darwin Core definition", 941 url = "https://rs.tdwg.org/dwc/terms/latestAgeOrHighestStage" 942 ) 943 ) 944 private String latestAgeOrHighestStage; 945 946 @Schema( 947 description = "The full name of the lowest possible geological biostratigraphic zone of the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 948 externalDocs = @ExternalDocumentation( 949 description = "Darwin Core definition", 950 url = "https://rs.tdwg.org/dwc/terms/lowestBiostratigraphicZone" 951 ) 952 ) 953 private String lowestBiostratigraphicZone; 954 955 @Schema( 956 description = "The full name of the highest possible geological biostratigraphic zone of the stratigraphic horizon from which the dwc:MaterialEntity was collected.", 957 externalDocs = @ExternalDocumentation( 958 description = "Darwin Core definition", 959 url = "https://rs.tdwg.org/dwc/terms/highestBiostratigraphicZone" 960 ) 961 ) 962 private String highestBiostratigraphicZone; 963 964 @Schema( 965 description = "The full name of the lithostratigraphic group from which the dwc:MaterialEntity was collected.", 966 externalDocs = @ExternalDocumentation( 967 description = "Darwin Core definition", 968 url = "https://rs.tdwg.org/dwc/terms/group" 969 ) 970 ) 971 private String group; 972 973 @Schema( 974 description = "The full name of the lithostratigraphic formation from which the dwc:MaterialEntity was collected.", 975 externalDocs = @ExternalDocumentation( 976 description = "Darwin Core definition", 977 url = "https://rs.tdwg.org/dwc/terms/formation" 978 ) 979 ) 980 private String formation; 981 982 @Schema( 983 description = "The full name of the lithostratigraphic member from which the dwc:MaterialEntity was collected.", 984 externalDocs = @ExternalDocumentation( 985 description = "Darwin Core definition", 986 url = "https://rs.tdwg.org/dwc/terms/member" 987 ) 988 ) 989 private String member; 990 991 @Schema( 992 description = "The full name of the lithostratigraphic bed from which the dwc:MaterialEntity was collected.", 993 externalDocs = @ExternalDocumentation( 994 description = "Darwin Core definition", 995 url = "https://rs.tdwg.org/dwc/terms/bed" 996 ) 997 ) 998 private String bed; 999 1000 1001 @Schema( 1002 description = "A person, group, or organization responsible for recording the original occurrence.", 1003 externalDocs = @ExternalDocumentation( 1004 description = "Darwin Core definition", 1005 url = "https://rs.tdwg.org/dwc/terms/recordedBy" 1006 ) 1007 ) 1008 private String recordedBy; 1009 1010 @Schema( 1011 description = "A list (concatenated and separated) of names of people, groups, or organizations who assigned the " + 1012 "Taxon to the occurrence.", 1013 externalDocs = @ExternalDocumentation( 1014 description = "Darwin Core definition", 1015 url = "https://rs.tdwg.org/dwc/terms/identifiedBy" 1016 ) 1017 ) 1018 private String identifiedBy; 1019 1020 @Schema( 1021 description = "A preparation or preservation method for a specimen.", 1022 externalDocs = @ExternalDocumentation( 1023 description = "Darwin Core definition", 1024 url = "https://rs.tdwg.org/dwc/terms/preparations" 1025 ) 1026 ) 1027 private String preparations; 1028 1029 @Schema( 1030 description = "The methods or protocols used during an Event, denoted by an IRI.", 1031 externalDocs = @ExternalDocumentation( 1032 description = "Darwin Core definition", 1033 url = "https://rs.tdwg.org/dwc/terms/samplingProtocol" 1034 ) 1035 ) 1036 private String samplingProtocol; 1037 1038 public Occurrence() { 1039 1040 } 1041 1042 /** 1043 * Create occurrence instance from existing verbatim one, copying over all data. 1044 */ 1045 public Occurrence(@Nullable VerbatimOccurrence verbatim) { 1046 if (verbatim != null) { 1047 setKey(verbatim.getKey()); 1048 setDatasetKey(verbatim.getDatasetKey()); 1049 setPublishingOrgKey(verbatim.getPublishingOrgKey()); 1050 setPublishingCountry(verbatim.getPublishingCountry()); 1051 setProtocol(verbatim.getProtocol()); 1052 setCrawlId(verbatim.getCrawlId()); 1053 if (verbatim.getLastCrawled() != null) { 1054 setLastCrawled(new Date(verbatim.getLastCrawled().getTime())); 1055 } 1056 if (verbatim.getVerbatimFields() != null) { 1057 getVerbatimFields().putAll(verbatim.getVerbatimFields()); 1058 } 1059 if (verbatim.getLastParsed() != null) { 1060 setLastParsed(verbatim.getLastParsed()); 1061 } 1062 setExtensions(verbatim.getExtensions()); 1063 } 1064 } 1065 1066 @Nullable 1067 public BasisOfRecord getBasisOfRecord() { 1068 return basisOfRecord; 1069 } 1070 1071 public void setBasisOfRecord(BasisOfRecord basisOfRecord) { 1072 this.basisOfRecord = basisOfRecord; 1073 } 1074 1075 @Nullable 1076 public Integer getIndividualCount() { 1077 return individualCount; 1078 } 1079 1080 public void setIndividualCount(Integer individualCount) { 1081 this.individualCount = individualCount; 1082 } 1083 1084 @Nullable 1085 public OccurrenceStatus getOccurrenceStatus() { 1086 return occurrenceStatus; 1087 } 1088 1089 public void setOccurrenceStatus(OccurrenceStatus occurrenceStatus) { 1090 this.occurrenceStatus = occurrenceStatus; 1091 } 1092 1093 @Nullable 1094 public Sex getSex() { 1095 return sex; 1096 } 1097 1098 public void setSex(Sex sex) { 1099 this.sex = sex; 1100 } 1101 1102 @Nullable 1103 public String getLifeStage() { 1104 return lifeStage; 1105 } 1106 1107 public void setLifeStage(String lifeStage) { 1108 this.lifeStage = lifeStage; 1109 } 1110 1111 @Nullable 1112 public String getEstablishmentMeans() { 1113 return establishmentMeans; 1114 } 1115 1116 public void setEstablishmentMeans(String establishmentMeans) { 1117 this.establishmentMeans = establishmentMeans; 1118 } 1119 1120 /** 1121 * The best matching, accepted GBIF backbone name usage representing this occurrence. 1122 * In case the verbatim scientific name and its classification can only be matched to a higher rank this will 1123 * represent the lowest matching rank. In the worst case this could just be for example Animalia. 1124 */ 1125 @Nullable 1126 public Integer getTaxonKey() { 1127 return taxonKey; 1128 } 1129 1130 public void setTaxonKey(Integer taxonKey) { 1131 this.taxonKey = taxonKey; 1132 } 1133 1134 @Nullable 1135 @Override 1136 public Integer getKingdomKey() { 1137 return kingdomKey; 1138 } 1139 1140 @Override 1141 public void setKingdomKey(@Nullable Integer kingdomKey) { 1142 this.kingdomKey = kingdomKey; 1143 } 1144 1145 @Nullable 1146 @Override 1147 public Integer getPhylumKey() { 1148 return phylumKey; 1149 } 1150 1151 @Override 1152 public void setPhylumKey(@Nullable Integer phylumKey) { 1153 this.phylumKey = phylumKey; 1154 } 1155 1156 @Nullable 1157 @Override 1158 public Integer getClassKey() { 1159 return classKey; 1160 } 1161 1162 @Override 1163 public void setClassKey(@Nullable Integer classKey) { 1164 this.classKey = classKey; 1165 } 1166 1167 @Nullable 1168 @Override 1169 public Integer getOrderKey() { 1170 return orderKey; 1171 } 1172 1173 @Override 1174 public void setOrderKey(@Nullable Integer orderKey) { 1175 this.orderKey = orderKey; 1176 } 1177 1178 @Nullable 1179 @Override 1180 public Integer getFamilyKey() { 1181 return familyKey; 1182 } 1183 1184 @Override 1185 public void setFamilyKey(@Nullable Integer familyKey) { 1186 this.familyKey = familyKey; 1187 } 1188 1189 @Nullable 1190 @Override 1191 public Integer getGenusKey() { 1192 return genusKey; 1193 } 1194 1195 @Override 1196 public void setGenusKey(@Nullable Integer genusKey) { 1197 this.genusKey = genusKey; 1198 } 1199 1200 @Nullable 1201 @Override 1202 public Integer getSubgenusKey() { 1203 return subgenusKey; 1204 } 1205 1206 @Override 1207 public void setSubgenusKey(@Nullable Integer subgenusKey) { 1208 this.subgenusKey = subgenusKey; 1209 } 1210 1211 @Nullable 1212 @Override 1213 public Integer getHigherRankKey(Rank rank) { 1214 return ClassificationUtils.getHigherRankKey(this, rank); 1215 } 1216 1217 /** 1218 * An ordered map with entries for all higher Linnean ranks excluding the taxonKey itself. 1219 * The map starts with the highest rank, e.g. the kingdom and maps the name usage key to its canonical name. 1220 * 1221 * @return map of higher ranks 1222 */ 1223 @NotNull 1224 @JsonIgnore 1225 public Map<Integer, String> getHigherClassificationMap() { 1226 return taxonKey == null ? ClassificationUtils.getHigherClassificationMap(this) 1227 : ClassificationUtils.getHigherClassificationMap(this, taxonKey, null, null); 1228 } 1229 1230 /** 1231 * The accepted species for this occurrence. In case the taxonKey is of a higher rank than species (e.g. genus) 1232 * speciesKey is null. In case taxonKey represents an infraspecific taxon the speciesKey points to the species 1233 * the infraspecies is classified as. In case of taxonKey being a species the speciesKey is the same. 1234 */ 1235 @Nullable 1236 @Override 1237 public Integer getSpeciesKey() { 1238 return speciesKey; 1239 } 1240 1241 @Override 1242 public void setSpeciesKey(@Nullable Integer speciesKey) { 1243 this.speciesKey = speciesKey; 1244 } 1245 1246 /** 1247 * The accepted taxon key from the GBIF backbone. 1248 */ 1249 @Nullable 1250 public Integer getAcceptedTaxonKey() { 1251 return acceptedTaxonKey; 1252 } 1253 1254 public void setAcceptedTaxonKey(Integer acceptedTaxonKey) { 1255 this.acceptedTaxonKey = acceptedTaxonKey; 1256 } 1257 1258 @Nullable 1259 public String getSpecificEpithet() { 1260 return specificEpithet; 1261 } 1262 1263 public void setSpecificEpithet(String specificEpithet) { 1264 this.specificEpithet = specificEpithet; 1265 } 1266 1267 @Nullable 1268 public String getInfraspecificEpithet() { 1269 return infraspecificEpithet; 1270 } 1271 1272 public void setInfraspecificEpithet(String infraspecificEpithet) { 1273 this.infraspecificEpithet = infraspecificEpithet; 1274 } 1275 1276 @Nullable 1277 public Rank getTaxonRank() { 1278 return taxonRank; 1279 } 1280 1281 public void setTaxonRank(Rank taxonRank) { 1282 this.taxonRank = taxonRank; 1283 } 1284 1285 /** 1286 * The status of the use of the scientificName as a label for a taxon. 1287 * The GBIF recommended controlled value vocabulary can be found at <a href="http://rs.gbif.org/vocabulary/gbif/taxonomic_status.xml">http://rs.gbif.org/vocabulary/gbif/taxonomic_status.xm</a>. 1288 */ 1289 @Nullable 1290 public TaxonomicStatus getTaxonomicStatus() { 1291 return taxonomicStatus; 1292 } 1293 1294 public void setTaxonomicStatus(TaxonomicStatus taxonomicStatus) { 1295 this.taxonomicStatus = taxonomicStatus; 1296 } 1297 1298 /** 1299 * The IUCN Red List Category. 1300 */ 1301 @Nullable 1302 public String getIucnRedListCategory() { 1303 return iucnRedListCategory; 1304 } 1305 1306 public void setIucnRedListCategory(String iucnRedListCategory) { 1307 this.iucnRedListCategory = iucnRedListCategory; 1308 } 1309 1310 /** 1311 * The scientific name for taxonKey from the GBIF backbone. 1312 */ 1313 @Nullable 1314 public String getScientificName() { 1315 return scientificName; 1316 } 1317 1318 public void setScientificName(@Nullable String scientificName) { 1319 this.scientificName = scientificName; 1320 } 1321 1322 /** 1323 * The verbatim scientific name as provided by the source. 1324 */ 1325 @Nullable 1326 @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) 1327 public String getVerbatimScientificName() { 1328 return getVerbatimField(DwcTerm.scientificName); 1329 } 1330 1331 public void setVerbatimScientificName(String scientificName) { 1332 //DO NOTHING 1333 } 1334 1335 /** 1336 * The accepted scientific name for the acceptedTaxonKey from the GBIF backbone. 1337 */ 1338 @Nullable 1339 public String getAcceptedScientificName() { 1340 return acceptedScientificName; 1341 } 1342 1343 public void setAcceptedScientificName(String acceptedScientificName) { 1344 this.acceptedScientificName = acceptedScientificName; 1345 } 1346 1347 @Nullable 1348 @Override 1349 public String getKingdom() { 1350 return kingdom; 1351 } 1352 1353 @Override 1354 public void setKingdom(@Nullable String kingdom) { 1355 this.kingdom = kingdom; 1356 } 1357 1358 @Nullable 1359 @Override 1360 public String getPhylum() { 1361 return phylum; 1362 } 1363 1364 @Override 1365 public void setPhylum(@Nullable String phylum) { 1366 this.phylum = phylum; 1367 } 1368 1369 @Nullable 1370 @Override 1371 public String getClazz() { 1372 return clazz; 1373 } 1374 1375 @Override 1376 public void setClazz(@Nullable String clazz) { 1377 this.clazz = clazz; 1378 } 1379 1380 @Nullable 1381 @Override 1382 public String getOrder() { 1383 return order; 1384 } 1385 1386 @Override 1387 public void setOrder(@Nullable String order) { 1388 this.order = order; 1389 } 1390 1391 @Nullable 1392 @Override 1393 public String getFamily() { 1394 return family; 1395 } 1396 1397 @Override 1398 public void setFamily(@Nullable String family) { 1399 this.family = family; 1400 } 1401 1402 @Nullable 1403 @Override 1404 public String getGenus() { 1405 return genus; 1406 } 1407 1408 @Override 1409 public void setGenus(@Nullable String genus) { 1410 this.genus = genus; 1411 } 1412 1413 @Nullable 1414 public String getGenericName() { 1415 return genericName; 1416 } 1417 1418 public void setGenericName(String genericName) { 1419 this.genericName = genericName; 1420 } 1421 1422 @Nullable 1423 @Override 1424 public String getSubgenus() { 1425 return subgenus; 1426 } 1427 1428 @Override 1429 public void setSubgenus(@Nullable String subgenus) { 1430 this.subgenus = subgenus; 1431 } 1432 1433 @Nullable 1434 @Override 1435 public String getHigherRank(Rank rank) { 1436 return ClassificationUtils.getHigherRank(this, rank); 1437 } 1438 1439 /** 1440 * The corresponding scientific name of the speciesKey from the GBIF backbone. 1441 */ 1442 @Nullable 1443 @Override 1444 public String getSpecies() { 1445 return species; 1446 } 1447 1448 @Override 1449 public void setSpecies(@Nullable String species) { 1450 this.species = species; 1451 } 1452 1453 @Nullable 1454 public Date getDateIdentified() { 1455 return dateIdentified == null ? null : new Date(dateIdentified.getTime()); 1456 } 1457 1458 public void setDateIdentified(@Nullable Date dateIdentified) { 1459 this.dateIdentified = dateIdentified == null ? null : new Date(dateIdentified.getTime()); 1460 } 1461 1462 /** 1463 * The decimalLongitude in decimal degrees always for the WGS84 datum. If a different geodetic datum was given the verbatim 1464 * coordinates are transformed into WGS84 values. 1465 */ 1466 @Nullable 1467 public Double getDecimalLongitude() { 1468 return decimalLongitude; 1469 } 1470 1471 public void setDecimalLongitude(@Nullable Double decimalLongitude) { 1472 this.decimalLongitude = decimalLongitude; 1473 } 1474 1475 @Nullable 1476 public Double getDecimalLatitude() { 1477 return decimalLatitude; 1478 } 1479 1480 public void setDecimalLatitude(@Nullable Double decimalLatitude) { 1481 this.decimalLatitude = decimalLatitude; 1482 } 1483 1484 /** 1485 * The uncertainty radius for lat/lon in meters. 1486 */ 1487 @Nullable 1488 public Double getCoordinateUncertaintyInMeters() { 1489 return coordinateUncertaintyInMeters; 1490 } 1491 1492 public void setCoordinateUncertaintyInMeters(@Nullable Double coordinateUncertaintyInMeters) { 1493 this.coordinateUncertaintyInMeters = coordinateUncertaintyInMeters; 1494 } 1495 1496 @Nullable 1497 public Double getCoordinatePrecision() { 1498 return coordinatePrecision; 1499 } 1500 1501 public void setCoordinatePrecision(Double coordinatePrecision) { 1502 this.coordinatePrecision = coordinatePrecision; 1503 } 1504 1505 /** 1506 * @deprecated to be removed in the public v2 of the API (see POR-3061) 1507 * The uncertainty for latitude in decimal degrees. 1508 * Note that the longitude degrees have a different accuracy in degrees which changes with latitude and is largest at the poles. 1509 */ 1510 @Nullable 1511 @Deprecated 1512 public Double getCoordinateAccuracy() { 1513 return coordinateAccuracy; 1514 } 1515 1516 public void setCoordinateAccuracy(@Nullable Double coordinateAccuracy) { 1517 this.coordinateAccuracy = coordinateAccuracy; 1518 } 1519 1520 /** 1521 * The geodetic datum for the interpreted decimal coordinates. 1522 * This is always WGS84 if a coordinate exists as we reproject other datums into WGS84. 1523 */ 1524 @Schema( 1525 description = "The geodetic datum for the interpreted decimal coordinates.\n\n" + 1526 "Coordinates are reprojected to WGS84 if they exist, so this field is either null or `WGS84`." 1527 ) 1528 @Nullable 1529 public String getGeodeticDatum() { 1530 if (decimalLatitude != null) { 1531 return GEO_DATUM; 1532 } 1533 return null; 1534 } 1535 1536 /** 1537 * This private method is needed for jackson deserialization only. 1538 */ 1539 private void setGeodeticDatum(String datum) { 1540 // ignore, we have a static WGS84 value 1541 } 1542 1543 /** 1544 * Elevation in meters usually above sea level (altitude). 1545 * </br> 1546 * The elevation is calculated using the equation: (minimumElevationInMeters + maximumElevationInMeters) / 2. 1547 */ 1548 @Nullable 1549 public Double getElevation() { 1550 return elevation; 1551 } 1552 1553 public void setElevation(@Nullable Double elevation) { 1554 this.elevation = elevation; 1555 } 1556 1557 /** 1558 * Elevation accuracy is the uncertainty for the elevation in meters. 1559 * </br> 1560 * The elevation accuracy is calculated using the equation: (maximumElevationInMeters - minimumElevationInMeters) / 2 1561 */ 1562 @Nullable 1563 public Double getElevationAccuracy() { 1564 return elevationAccuracy; 1565 } 1566 1567 public void setElevationAccuracy(@Nullable Double elevationAccuracy) { 1568 this.elevationAccuracy = elevationAccuracy; 1569 } 1570 1571 /** 1572 * Depth in meters below the surface. Complimentary to elevation, the depth can be 10 meters below the surface of a 1573 * lake in 1100m (=elevation). 1574 * </br> 1575 * The depth is calculated using the equation: (minimumDepthInMeters + maximumDepthInMeters) / 2. 1576 */ 1577 @Nullable 1578 public Double getDepth() { 1579 return depth; 1580 } 1581 1582 public void setDepth(@Nullable Double depth) { 1583 this.depth = depth; 1584 } 1585 1586 /** 1587 * Depth accuracy is the uncertainty for the depth in meters. 1588 * </br> 1589 * The depth accuracy is calculated using the equation: (maximumDepthInMeters - minimumDepthInMeters) / 2 1590 */ 1591 @Nullable 1592 public Double getDepthAccuracy() { 1593 return depthAccuracy; 1594 } 1595 1596 public void setDepthAccuracy(@Nullable Double depthAccuracy) { 1597 this.depthAccuracy = depthAccuracy; 1598 } 1599 1600 @Nullable 1601 public Continent getContinent() { 1602 return continent; 1603 } 1604 1605 public void setContinent(@Nullable Continent continent) { 1606 this.continent = continent; 1607 } 1608 1609 @Schema( 1610 description = "The 2-letter country code (as per ISO-3166-1) of the country, territory or area in which the " + 1611 "occurrence was recorded.", 1612 externalDocs = @ExternalDocumentation( 1613 description = "Darwin Core definition", 1614 url = "https://rs.tdwg.org/dwc/terms/countryCode" 1615 ) 1616 ) 1617 @Nullable 1618 @JsonProperty("countryCode") 1619 public Country getCountry() { 1620 return country; 1621 } 1622 1623 public void setCountry(@Nullable Country country) { 1624 this.country = country; 1625 } 1626 1627 @Nullable 1628 @JsonProperty("gbifRegion") 1629 public GbifRegion getGbifRegion() { 1630 return Optional.ofNullable(country).map(Country::getGbifRegion).orElse(null); 1631 } 1632 1633 private void setGbifRegion(String gbifRegion) { 1634 // ignore, setter only to avoid JSON being written into the fields map 1635 } 1636 1637 /** 1638 * Renders the country title as a JSON property country in addition to the ISO 3166 2 letter countryCode being 1639 * serialized by the regular country Java property. 1640 * Made private to use it only for JSON serialization and not within Java code. 1641 */ 1642 @Schema( 1643 description = "The title (as per ISO-3166-1) of the country, territory or area in which the " + 1644 "occurrence was recorded.", 1645 externalDocs = @ExternalDocumentation( 1646 description = "Darwin Core definition", 1647 url = "https://rs.tdwg.org/dwc/terms/country" 1648 ) 1649 ) 1650 @Nullable 1651 @JsonProperty("country") 1652 private String getCountryTitle() { 1653 return country == null ? null : country.getTitle(); 1654 } 1655 1656 private void setCountryTitle(String country) { 1657 // ignore, setter only to avoid JSON being written into the fields map 1658 } 1659 1660 @Nullable 1661 public String getStateProvince() { 1662 return stateProvince; 1663 } 1664 1665 public void setStateProvince(@Nullable String stateProvince) { 1666 this.stateProvince = stateProvince; 1667 } 1668 1669 @Nullable 1670 public String getWaterBody() { 1671 return waterBody; 1672 } 1673 1674 public void setWaterBody(@Nullable String waterBody) { 1675 this.waterBody = waterBody; 1676 } 1677 1678 /** 1679 * The distance in metres from a known centroid, e.g. a country centroid. 1680 */ 1681 public Double getDistanceFromCentroidInMeters() { 1682 return distanceFromCentroidInMeters; 1683 } 1684 1685 public void setDistanceFromCentroidInMeters(Double distanceFromCentroidInMeters) { 1686 this.distanceFromCentroidInMeters = distanceFromCentroidInMeters; 1687 } 1688 1689 @Nullable 1690 public String getHigherGeography() { 1691 return higherGeography; 1692 } 1693 1694 public void setHigherGeography(String higherGeography) { 1695 this.higherGeography = higherGeography; 1696 } 1697 1698 @Nullable 1699 public String getGeoreferencedBy() { 1700 return georeferencedBy; 1701 } 1702 1703 public void setGeoreferencedBy(String georeferencedBy) { 1704 this.georeferencedBy = georeferencedBy; 1705 } 1706 1707 /** 1708 * The full year of the event date. 1709 * 1710 * @return the year of the event date 1711 */ 1712 @Min(1500) 1713 @Max(2030) 1714 @Nullable 1715 public Integer getYear() { 1716 return year; 1717 } 1718 1719 public void setYear(@Nullable Integer year) { 1720 this.year = year; 1721 } 1722 1723 /** 1724 * The month of the year of the event date starting with zero for january following {@link Date}. 1725 * 1726 * @return the month of the event date 1727 */ 1728 @Min(1) 1729 @Max(12) 1730 @Nullable 1731 public Integer getMonth() { 1732 return month; 1733 } 1734 1735 public void setMonth(@Nullable Integer month) { 1736 this.month = month; 1737 } 1738 1739 /** 1740 * The day of the month of the event date. 1741 * 1742 * @return the day of the event date 1743 */ 1744 @Min(1) 1745 @Max(31) 1746 @Nullable 1747 public Integer getDay() { 1748 return day; 1749 } 1750 1751 public void setDay(@Nullable Integer day) { 1752 this.day = day; 1753 } 1754 1755 /** 1756 * The date the occurrence was recorded or collected. 1757 */ 1758 @Nullable 1759 public IsoDateInterval getEventDate() { 1760 return eventDate == null ? null : new IsoDateInterval(eventDate.getFrom(), eventDate.getTo()); 1761 } 1762 1763 public void setEventDate(@Nullable IsoDateInterval eventDate) { 1764 this.eventDate = eventDate == null ? null : new IsoDateInterval(eventDate.getFrom(), eventDate.getTo()); 1765 } 1766 1767 /** 1768 * The earliest integer day of the year of the event. 1769 * 1770 * @return the earliest integer day of the event date 1771 */ 1772 @Min(1) 1773 @Max(366) 1774 @Nullable 1775 public Integer getStartDayOfYear() { 1776 return startDayOfYear; 1777 } 1778 1779 public void setStartDayOfYear(@Nullable Integer startDayOfYear) { 1780 this.startDayOfYear = startDayOfYear; 1781 } 1782 1783 /** 1784 * The latest integer day of the year of the event. 1785 * 1786 * @return the latest integer day of the event date 1787 */ 1788 @Min(1) 1789 @Max(366) 1790 @Nullable 1791 public Integer getEndDayOfYear() { 1792 return endDayOfYear; 1793 } 1794 1795 public void setEndDayOfYear(@Nullable Integer endDayOfYear) { 1796 this.endDayOfYear = endDayOfYear; 1797 } 1798 1799 @Nullable 1800 public String getTypeStatus() { 1801 return typeStatus; 1802 } 1803 1804 public void setTypeStatus(@Nullable String typeStatus) { 1805 this.typeStatus = typeStatus; 1806 } 1807 1808 /** 1809 * The scientific name the type status of this specimen applies to. 1810 */ 1811 @Nullable 1812 public String getTypifiedName() { 1813 return typifiedName; 1814 } 1815 1816 public void setTypifiedName(@Nullable String typifiedName) { 1817 this.typifiedName = typifiedName; 1818 } 1819 1820 /** 1821 * A set of issues found for this occurrence. 1822 */ 1823 @NotNull 1824 public Set<OccurrenceIssue> getIssues() { 1825 return issues; 1826 } 1827 1828 public void setIssues(Set<OccurrenceIssue> issues) { 1829 Objects.requireNonNull(issues, "Issues cannot be null"); 1830 EnumSet<OccurrenceIssue> set = EnumSet.noneOf(OccurrenceIssue.class); 1831 set.addAll(issues); 1832 this.issues = set; 1833 } 1834 1835 public void addIssue(OccurrenceIssue issue) { 1836 Objects.requireNonNull(issue, "Issue needs to be specified"); 1837 issues.add(issue); 1838 } 1839 1840 /** 1841 * The interpreted dc:modified from the verbatim source data. 1842 * Ideally indicating when a record was last modified in the source. 1843 */ 1844 @Nullable 1845 public Date getModified() { 1846 return modified == null ? null : new Date(modified.getTime()); 1847 } 1848 1849 public void setModified(@Nullable Date modified) { 1850 this.modified = modified == null ? null : new Date(modified.getTime()); 1851 } 1852 1853 /** 1854 * The date this occurrence last went through the interpretation phase of the GBIF indexing. 1855 */ 1856 @Nullable 1857 public Date getLastInterpreted() { 1858 return lastInterpreted == null ? null : new Date(lastInterpreted.getTime()); 1859 } 1860 1861 public void setLastInterpreted(@Nullable Date lastInterpreted) { 1862 this.lastInterpreted = lastInterpreted == null ? null : new Date(lastInterpreted.getTime()); 1863 } 1864 1865 /** 1866 * An external link to more details, the records "homepage". 1867 */ 1868 @Nullable 1869 public URI getReferences() { 1870 return references; 1871 } 1872 1873 public void setReferences(URI references) { 1874 this.references = references; 1875 } 1876 1877 /** 1878 * A number or enumeration value for the quantity of organisms. 1879 */ 1880 @Nullable 1881 public Double getOrganismQuantity() { 1882 return organismQuantity; 1883 } 1884 1885 public void setOrganismQuantity(@Nullable Double organismQuantity) { 1886 this.organismQuantity = organismQuantity; 1887 } 1888 1889 /** 1890 * The type of quantification system used for the quantity of organisms. 1891 */ 1892 @Nullable 1893 public String getOrganismQuantityType() { 1894 return organismQuantityType; 1895 } 1896 1897 public void setOrganismQuantityType(@Nullable String organismQuantityType) { 1898 this.organismQuantityType = organismQuantityType; 1899 } 1900 1901 /** 1902 * The unit of measurement of the size (time duration, length, area, or volume) of a sample in a sampling event. 1903 */ 1904 @Nullable 1905 public String getSampleSizeUnit() { 1906 return sampleSizeUnit; 1907 } 1908 1909 public void setSampleSizeUnit(@Nullable String sampleSizeUnit) { 1910 this.sampleSizeUnit = sampleSizeUnit; 1911 } 1912 1913 /** 1914 * A numeric value for a measurement of the size (time duration, length, area, or volume) of a sample in a sampling event. 1915 */ 1916 @Nullable 1917 public Double getSampleSizeValue() { 1918 return sampleSizeValue; 1919 } 1920 1921 public void setSampleSizeValue(@Nullable Double sampleSizeValue) { 1922 this.sampleSizeValue = sampleSizeValue; 1923 } 1924 1925 /** 1926 * Calculated filed organismQuantity / sampleSizeValue, if the type is identical 1927 */ 1928 @Nullable 1929 public Double getRelativeOrganismQuantity() { 1930 return relativeOrganismQuantity; 1931 } 1932 1933 public void setRelativeOrganismQuantity(@Nullable Double relativeOrganismQuantity) { 1934 this.relativeOrganismQuantity = relativeOrganismQuantity; 1935 } 1936 1937 /** 1938 * Flag occurrence when associatedSequences/extension exists 1939 */ 1940 public boolean getIsSequenced() { 1941 return isSequenced; 1942 } 1943 1944 public void setIsSequenced(boolean isSequenced) { 1945 this.isSequenced = isSequenced; 1946 } 1947 1948 /** 1949 * A list (concatenated and separated) of identifiers (publication, global unique identifier, URI) of genetic 1950 * sequence information associated with the material entity. 1951 */ 1952 @Nullable 1953 public String getAssociatedSequences() { 1954 return associatedSequences; 1955 } 1956 1957 public void setAssociatedSequences(String associatedSequences) { 1958 this.associatedSequences = associatedSequences; 1959 } 1960 1961 /** 1962 * Applied license to the occurrence record or dataset to which this record belongs to. 1963 */ 1964 @NotNull 1965 public License getLicense() { 1966 return license; 1967 } 1968 1969 public void setLicense(License license) { 1970 this.license = license; 1971 } 1972 1973 @NotNull 1974 public List<Identifier> getIdentifiers() { 1975 return identifiers; 1976 } 1977 1978 public void setIdentifiers(List<Identifier> identifiers) { 1979 this.identifiers = identifiers; 1980 } 1981 1982 @NotNull 1983 public List<MediaObject> getMedia() { 1984 return media; 1985 } 1986 1987 public void setMedia(List<MediaObject> media) { 1988 this.media = media; 1989 } 1990 1991 @NotNull 1992 public List<MeasurementOrFact> getFacts() { 1993 return facts; 1994 } 1995 1996 public void setFacts(List<MeasurementOrFact> facts) { 1997 this.facts = facts; 1998 } 1999 2000 @NotNull 2001 public List<OccurrenceRelation> getRelations() { 2002 return relations; 2003 } 2004 2005 public void setRelations(List<OccurrenceRelation> relations) { 2006 this.relations = relations; 2007 } 2008 2009 @NotNull 2010 public List<AgentIdentifier> getRecordedByIds() { 2011 return recordedByIds; 2012 } 2013 2014 public void setRecordedByIds(List<AgentIdentifier> recordedByIds) { 2015 this.recordedByIds = recordedByIds; 2016 } 2017 2018 @NotNull 2019 public List<AgentIdentifier> getIdentifiedByIds() { 2020 return identifiedByIds; 2021 } 2022 2023 public void setIdentifiedByIds(List<AgentIdentifier> identifiedByIds) { 2024 this.identifiedByIds = identifiedByIds; 2025 } 2026 2027 @NotNull 2028 public Gadm getGadm() { 2029 return gadm; 2030 } 2031 2032 public void setGadm(Gadm gadm) { 2033 this.gadm = gadm; 2034 } 2035 2036 @Nullable 2037 @Experimental 2038 public String getInstitutionKey() { 2039 return institutionKey; 2040 } 2041 2042 public void setInstitutionKey(String institutionKey) { 2043 this.institutionKey = institutionKey; 2044 } 2045 2046 @Nullable 2047 @Experimental 2048 public String getCollectionKey() { 2049 return collectionKey; 2050 } 2051 2052 public void setCollectionKey(String collectionKey) { 2053 this.collectionKey = collectionKey; 2054 } 2055 2056 public boolean getIsInCluster() { 2057 return isInCluster; 2058 } 2059 2060 public void setIsInCluster(boolean isInCluster) { 2061 this.isInCluster = isInCluster; 2062 } 2063 2064 @Nullable 2065 public String getDegreeOfEstablishment() { 2066 return degreeOfEstablishment; 2067 } 2068 2069 public void setDegreeOfEstablishment(String degreeOfEstablishment) { 2070 this.degreeOfEstablishment = degreeOfEstablishment; 2071 } 2072 2073 @Nullable 2074 public String getPathway() { 2075 return pathway; 2076 } 2077 2078 public void setPathway(String pathway) { 2079 this.pathway = pathway; 2080 } 2081 2082 public String getDatasetID() { 2083 return datasetID; 2084 } 2085 2086 public void setDatasetID(String datasetID) { 2087 this.datasetID = datasetID; 2088 } 2089 2090 public String getDatasetName() { 2091 return datasetName; 2092 } 2093 2094 public void setDatasetName(String datasetName) { 2095 this.datasetName = datasetName; 2096 } 2097 2098 public String getOtherCatalogNumbers() { 2099 return otherCatalogNumbers; 2100 } 2101 2102 public void setOtherCatalogNumbers(String otherCatalogNumbers) { 2103 this.otherCatalogNumbers = otherCatalogNumbers; 2104 } 2105 2106 @Nullable 2107 public String getEarliestEonOrLowestEonothem() { 2108 return earliestEonOrLowestEonothem; 2109 } 2110 2111 public void setEarliestEonOrLowestEonothem(String earliestEonOrLowestEonothem) { 2112 this.earliestEonOrLowestEonothem = earliestEonOrLowestEonothem; 2113 } 2114 2115 @Nullable 2116 public String getLatestEonOrHighestEonothem() { 2117 return latestEonOrHighestEonothem; 2118 } 2119 2120 public void setLatestEonOrHighestEonothem(String latestEonOrHighestEonothem) { 2121 this.latestEonOrHighestEonothem = latestEonOrHighestEonothem; 2122 } 2123 2124 @Nullable 2125 public String getEarliestEraOrLowestErathem() { 2126 return earliestEraOrLowestErathem; 2127 } 2128 2129 public void setEarliestEraOrLowestErathem(String earliestEraOrLowestErathem) { 2130 this.earliestEraOrLowestErathem = earliestEraOrLowestErathem; 2131 } 2132 2133 @Nullable 2134 public String getLatestEraOrHighestErathem() { 2135 return latestEraOrHighestErathem; 2136 } 2137 2138 public void setLatestEraOrHighestErathem(String latestEraOrHighestErathem) { 2139 this.latestEraOrHighestErathem = latestEraOrHighestErathem; 2140 } 2141 2142 @Nullable 2143 public String getEarliestPeriodOrLowestSystem() { 2144 return earliestPeriodOrLowestSystem; 2145 } 2146 2147 public void setEarliestPeriodOrLowestSystem(String earliestPeriodOrLowestSystem) { 2148 this.earliestPeriodOrLowestSystem = earliestPeriodOrLowestSystem; 2149 } 2150 2151 @Nullable 2152 public String getLatestPeriodOrHighestSystem() { 2153 return latestPeriodOrHighestSystem; 2154 } 2155 2156 public void setLatestPeriodOrHighestSystem(String latestPeriodOrHighestSystem) { 2157 this.latestPeriodOrHighestSystem = latestPeriodOrHighestSystem; 2158 } 2159 2160 @Nullable 2161 public String getEarliestEpochOrLowestSeries() { 2162 return earliestEpochOrLowestSeries; 2163 } 2164 2165 public void setEarliestEpochOrLowestSeries(String earliestEpochOrLowestSeries) { 2166 this.earliestEpochOrLowestSeries = earliestEpochOrLowestSeries; 2167 } 2168 2169 @Nullable 2170 public String getLatestEpochOrHighestSeries() { 2171 return latestEpochOrHighestSeries; 2172 } 2173 2174 public void setLatestEpochOrHighestSeries(String latestEpochOrHighestSeries) { 2175 this.latestEpochOrHighestSeries = latestEpochOrHighestSeries; 2176 } 2177 2178 @Nullable 2179 public String getEarliestAgeOrLowestStage() { 2180 return earliestAgeOrLowestStage; 2181 } 2182 2183 public void setEarliestAgeOrLowestStage(String earliestAgeOrLowestStage) { 2184 this.earliestAgeOrLowestStage = earliestAgeOrLowestStage; 2185 } 2186 2187 @Nullable 2188 public String getLatestAgeOrHighestStage() { 2189 return latestAgeOrHighestStage; 2190 } 2191 2192 public void setLatestAgeOrHighestStage(String latestAgeOrHighestStage) { 2193 this.latestAgeOrHighestStage = latestAgeOrHighestStage; 2194 } 2195 2196 @Nullable 2197 public String getLowestBiostratigraphicZone() { 2198 return lowestBiostratigraphicZone; 2199 } 2200 2201 public void setLowestBiostratigraphicZone(String lowestBiostratigraphicZone) { 2202 this.lowestBiostratigraphicZone = lowestBiostratigraphicZone; 2203 } 2204 2205 @Nullable 2206 public String getHighestBiostratigraphicZone() { 2207 return highestBiostratigraphicZone; 2208 } 2209 2210 public void setHighestBiostratigraphicZone(String highestBiostratigraphicZone) { 2211 this.highestBiostratigraphicZone = highestBiostratigraphicZone; 2212 } 2213 2214 @Nullable 2215 public String getGroup() { 2216 return group; 2217 } 2218 2219 public void setGroup(String group) { 2220 this.group = group; 2221 } 2222 2223 @Nullable 2224 public String getFormation() { 2225 return formation; 2226 } 2227 2228 public void setFormation(String formation) { 2229 this.formation = formation; 2230 } 2231 2232 @Nullable 2233 public String getMember() { 2234 return member; 2235 } 2236 2237 public void setMember(String member) { 2238 this.member = member; 2239 } 2240 2241 @Nullable 2242 public String getBed() { 2243 return bed; 2244 } 2245 2246 public void setBed(String bed) { 2247 this.bed = bed; 2248 } 2249 2250 public String getRecordedBy() { 2251 return recordedBy; 2252 } 2253 2254 public void setRecordedBy(String recordedBy) { 2255 this.recordedBy = recordedBy; 2256 } 2257 2258 public String getIdentifiedBy() { 2259 return identifiedBy; 2260 } 2261 2262 public void setIdentifiedBy(String identifiedBy) { 2263 this.identifiedBy = identifiedBy; 2264 } 2265 2266 public String getPreparations() { 2267 return preparations; 2268 } 2269 2270 public void setPreparations(String preparations) { 2271 this.preparations = preparations; 2272 } 2273 2274 public String getSamplingProtocol() { 2275 return samplingProtocol; 2276 } 2277 2278 public void setSamplingProtocol(String samplingProtocol) { 2279 this.samplingProtocol = samplingProtocol; 2280 } 2281 2282 /** 2283 * Convenience method checking if any spatial validation rule has not passed. 2284 * Primarily used to indicate that the record should not be displayed on a map. 2285 */ 2286 @JsonIgnore 2287 public boolean hasSpatialIssue() { 2288 for (OccurrenceIssue rule : OccurrenceIssue.GEOSPATIAL_RULES) { 2289 if (issues.contains(rule)) { 2290 return true; 2291 } 2292 } 2293 return false; 2294 } 2295 2296 /** 2297 * This private method is only for serialization via jackson and not exposed anywhere else! 2298 * It maps the verbatimField terms into properties with their simple name or qualified names for UnknownTerms. 2299 */ 2300 @JsonAnyGetter 2301 private Map<String, String> jsonVerbatimFields() { 2302 Map<String, String> extendedProps = new HashMap<>(); 2303 for (Map.Entry<Term, String> prop : getVerbatimFields().entrySet()) { 2304 Term t = prop.getKey(); 2305 if (t instanceof UnknownTerm || PROPERTIES.contains(t.simpleName())) { 2306 extendedProps.put(t.qualifiedName(), prop.getValue()); 2307 } else { 2308 // render all terms in controlled enumerations as simple names only - unless we have a property of that name already! 2309 extendedProps.put(t.simpleName(), prop.getValue()); 2310 } 2311 } 2312 return extendedProps; 2313 } 2314}