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.registry; 015 016import lombok.Data; 017import lombok.NoArgsConstructor; 018 019import org.gbif.api.model.common.DOI; 020import org.gbif.api.model.registry.eml.Collection; 021import org.gbif.api.model.registry.eml.DataDescription; 022import org.gbif.api.model.registry.eml.KeywordCollection; 023import org.gbif.api.model.registry.eml.Project; 024import org.gbif.api.model.registry.eml.SamplingDescription; 025import org.gbif.api.model.registry.eml.TaxonomicCoverages; 026import org.gbif.api.model.registry.eml.curatorial.CuratorialUnitComposite; 027import org.gbif.api.model.registry.eml.geospatial.GeospatialCoverage; 028import org.gbif.api.model.registry.eml.temporal.TemporalCoverage; 029import org.gbif.api.util.HttpURI; 030import org.gbif.api.vocabulary.Country; 031import org.gbif.api.vocabulary.DatasetSubtype; 032import org.gbif.api.vocabulary.DatasetType; 033import org.gbif.api.vocabulary.Language; 034import org.gbif.api.vocabulary.License; 035import org.gbif.api.vocabulary.MaintenanceUpdateFrequency; 036 037import java.net.URI; 038import java.util.ArrayList; 039import java.util.Date; 040import java.util.HashSet; 041import java.util.List; 042import java.util.Objects; 043import java.util.Set; 044import java.util.StringJoiner; 045import java.util.UUID; 046 047import javax.annotation.Nullable; 048import javax.validation.Valid; 049import javax.validation.constraints.Min; 050import javax.validation.constraints.NotNull; 051import javax.validation.constraints.Null; 052import javax.validation.constraints.Size; 053 054import io.swagger.v3.oas.annotations.media.Schema; 055 056/** 057 * A GBIF dataset which provides occurrence data, checklist data, sampling event data or metadata. 058 * This Dataset class is covering all the GBIF metadata profile v1.3, but only a few properties are kept in the 059 * database table: 060 * <ul> 061 * <li>key</li> 062 * <li>parentDatasetKey</li> 063 * <li>duplicateOfDatasetKey</li> 064 * <li>version</li> 065 * <li>installationKey</li> 066 * <li>publishingOrganizationKey</li> 067 * <li>publishingOrganizationName</li> 068 * <li>networkKeys</li> 069 * <li>license</li> 070 * <li>maintenanceUpdateFrequency</li> 071 * <li>external</li> 072 * <li>numConstituents</li> 073 * <li>type</li> 074 * <li>subtype</li> 075 * <li>title</li> 076 * <li>alias</li> 077 * <li>abbreviation</li> 078 * <li>description</li> 079 * <li>language</li> 080 * <li>homepage</li> 081 * <li>logoUrl</li> 082 * <li>citation</li> 083 * <li>rights</li> 084 * <li>lockedForAutoUpdate</li> 085 * <li>createdBy</li> 086 * <li>modifiedBy</li> 087 * <li>created</li> 088 * <li>modified</li> 089 * <li>deleted</li> 090 * </ul> 091 * 092 * @see <a href="http://rs.gbif.org/schema/eml-gbif-profile/dev/eml.xsd">GBIF EML Profile XML Schema</a> 093 */ 094@SuppressWarnings({"unused", "LombokSetterMayBeUsed", "LombokGetterMayBeUsed"}) 095public class Dataset 096 implements NetworkEntity, 097 Contactable, 098 Endpointable, 099 MachineTaggable, 100 Taggable, 101 Identifiable, 102 Commentable, 103 LenientEquals<Dataset> { 104 105 @Schema( 106 description = "Unique GBIF key for the dataset. This is used in the" + 107 "GBIF API, but outside GBIF it is best to refer to a dataset by its DOI.", 108 accessMode = Schema.AccessMode.READ_ONLY 109 ) 110 private UUID key; 111 112 @Schema( 113 description = "If set, this dataset is a sub-dataset of the parent." 114 ) 115 private UUID parentDatasetKey; 116 117 @Schema( 118 description = "A dataset of which this dataset is a duplicate. Typically, " + 119 "this means this dataset is an old version of the duplicated dataset, " + 120 "which has replaced this dataset. Therefore **this link is usually found " + 121 "on deleted datasets**." 122 ) 123 private UUID duplicateOfDatasetKey; 124 125 @Schema( 126 description = "The installation providing access to the source dataset.\n\n" + 127 "*(NB Not required for updates.)*" 128 ) 129 private UUID installationKey; 130 131 @Schema( 132 description = "The publishing organization publishing this dataset.\n\n" + 133 "*(NB Not required for updates.)*" 134 ) 135 private UUID publishingOrganizationKey; 136 137 @Schema( 138 description = "The publishing organization name.\n\n" + 139 "*(NB Not required for updates.)*" 140 ) 141 private String publishingOrganizationName; 142 143 @Schema( 144 description = "A list of GBIF Networks to which this dataset belongs." 145 ) 146 private List<UUID> networkKeys; 147 148 @Schema( 149 description = "The primary Digital Object Identifier (DOI) for this dataset.", 150 implementation = String.class, 151 pattern = "(10(?:\\.[0-9]+)+)" + "/(.+)" 152 ) 153 private DOI doi; 154 155 @Schema( 156 description = "The version of the published dataset." 157 ) 158 private String version; 159 160 @Schema( 161 description = "Not currently used." 162 ) 163 private boolean external; 164 165 @Schema( 166 description = "If set, the number of sub-datasets of this parent dataset." 167 ) 168 private int numConstituents; 169 170 @Schema( 171 description = "The primary type of the dataset.\n\n" + 172 "*(NB Not required for updates.)*" 173 ) 174 private DatasetType type; 175 176 @Schema( 177 description = "The sub-type of the dataset." 178 ) 179 private DatasetSubtype subtype; 180 181 @Schema( 182 description = "Concise name of the dataset." 183 ) 184 private String shortName; 185 186 @Schema( 187 description = "The title of the dataset.\n\n" + 188 "*(NB Not required for updates.)*" 189 ) 190 private String title; 191 192 @Schema( 193 description = "An alias for this dataset. Rarely used." 194 ) 195 private String alias; 196 197 @Schema( 198 description = "An abbreviation for this dataset. Rarely used." 199 ) 200 private String abbreviation; 201 202 @Schema( 203 description = "A description of the dataset." 204 ) 205 private String description; 206 207 @Schema( 208 description = "The language of the dataset metadata.\n\n" + 209 "*(NB Not required for updates.)*" 210 ) 211 private Language language = Language.ENGLISH; // sensible default as it is not null 212 213 @Schema( 214 description = "A homepage with further details on the dataset." 215 ) 216 private URI homepage; 217 218 @Schema( 219 description = "A logo for the dataset, accessible over HTTP." 220 ) 221 private URI logoUrl; 222 223 @Schema( 224 description = "The citation recommended by GBIF for use when citing this dataset." 225 ) 226 private Citation citation = new Citation(); 227 228 @Schema( 229 description = "Contacts use to generate a citation." 230 ) 231 private List<CitationContact> contactsCitation = new ArrayList<>(); 232 233 @Schema( 234 description = "Intellectual property rights applied to this dataset.\n\n" + 235 "*Rarely used, see `license` instead.*" 236 ) 237 private String rights; 238 239 @Schema( 240 description = "If true, any new or updated metadata is ignored.\n\n" + 241 "This is generally used when the publisher has technical problems or " + 242 "limitations with their publication system.", 243 accessMode = Schema.AccessMode.READ_ONLY 244 ) 245 private boolean lockedForAutoUpdate; 246 247 @Schema( 248 description = "The GBIF username of the creator of the dataset.", 249 accessMode = Schema.AccessMode.READ_ONLY 250 ) 251 private String createdBy; 252 253 @Schema( 254 description = "The GBIF username of the last user to modify the dataset.", 255 accessMode = Schema.AccessMode.READ_ONLY 256 ) 257 private String modifiedBy; 258 259 @Schema( 260 description = "Timestamp of when the dataset was created.", 261 accessMode = Schema.AccessMode.READ_ONLY 262 ) 263 private Date created; 264 265 @Schema( 266 description = "Timestamp of when the dataset was modified.", 267 accessMode = Schema.AccessMode.READ_ONLY 268 ) 269 private Date modified; 270 271 @Schema( 272 description = "If present, the dataset was deleted at this time. " + 273 "It is possible for it to be restored in the future.", 274 accessMode = Schema.AccessMode.READ_ONLY 275 ) 276 private Date deleted; 277 278 @Schema( 279 description = "A list of contacts associated with this dataset.", 280 accessMode = Schema.AccessMode.READ_ONLY 281 ) 282 private List<Contact> contacts = new ArrayList<>(); 283 284 @Schema( 285 description = "A list of endpoints associated with this dataset.", 286 accessMode = Schema.AccessMode.READ_ONLY 287 ) 288 private List<Endpoint> endpoints = new ArrayList<>(); 289 290 @Schema( 291 description = "A list of machine tags associated with this dataset.", 292 accessMode = Schema.AccessMode.READ_ONLY 293 ) 294 private List<MachineTag> machineTags = new ArrayList<>(); 295 296 @Schema( 297 description = "A list of tags associated with this dataset.", 298 accessMode = Schema.AccessMode.READ_ONLY 299 ) 300 private List<Tag> tags = new ArrayList<>(); 301 302 @Schema( 303 description = "A list of identifiers associated with this dataset.", 304 accessMode = Schema.AccessMode.READ_ONLY 305 ) 306 private List<Identifier> identifiers = new ArrayList<>(); 307 308 @Schema( 309 description = "A list of comments associated with this dataset.", 310 accessMode = Schema.AccessMode.READ_ONLY 311 ) 312 private List<Comment> comments = new ArrayList<>(); 313 314 // EML specific properties which are not persisted on the dataset table! 315 @Schema( 316 description = "Citations retrieved from this dataset's metadata documents.", 317 accessMode = Schema.AccessMode.READ_ONLY 318 ) 319 private List<Citation> bibliographicCitations = new ArrayList<>(); 320 321 @Schema( 322 description = "Curatorial unit information retrieved from this dataset's metadata documents.", 323 accessMode = Schema.AccessMode.READ_ONLY 324 ) 325 private List<CuratorialUnitComposite> curatorialUnits = new ArrayList<>(); 326 327 @Schema( 328 description = "Taxonomic coverage information retrieved from this dataset's metadata documents.", 329 accessMode = Schema.AccessMode.READ_ONLY 330 ) 331 private List<TaxonomicCoverages> taxonomicCoverages = new ArrayList<>(); 332 333 @Schema( 334 description = "Geographic coverage description retrieved from this dataset's metadata documents.", 335 accessMode = Schema.AccessMode.READ_ONLY 336 ) 337 private String geographicCoverageDescription; 338 339 @Schema( 340 description = "Geospatial coverage information retrieved from this dataset's metadata documents.", 341 accessMode = Schema.AccessMode.READ_ONLY 342 ) 343 private List<GeospatialCoverage> geographicCoverages = new ArrayList<>(); 344 345 @Schema( 346 description = "Temporal coverage information retrieved from this dataset's metadata documents.", 347 accessMode = Schema.AccessMode.READ_ONLY 348 ) 349 private List<TemporalCoverage> temporalCoverages = new ArrayList<>(); 350 351 @Schema( 352 description = "Keyword collections retrieved from this dataset's metadata documents.", 353 accessMode = Schema.AccessMode.READ_ONLY 354 ) 355 private List<KeywordCollection> keywordCollections = new ArrayList<>(); 356 357 @Schema( 358 description = "Project information retrieved from this dataset's metadata documents.", 359 accessMode = Schema.AccessMode.READ_ONLY 360 ) 361 private Project project; 362 363 @Schema( 364 description = "Sampling description retrieved from this dataset's metadata documents.", 365 accessMode = Schema.AccessMode.READ_ONLY 366 ) 367 private SamplingDescription samplingDescription; 368 369 @Schema( 370 description = "Country coverage information retrieved from this dataset's metadata documents.", 371 accessMode = Schema.AccessMode.READ_ONLY 372 ) 373 private Set<Country> countryCoverage = new HashSet<>(); 374 375 @Schema( 376 description = "Collection information retrieved from this dataset's metadata documents.", 377 accessMode = Schema.AccessMode.READ_ONLY 378 ) 379 private List<Collection> collections = new ArrayList<>(); 380 381 @Schema( 382 description = "Data description information retrieved from this dataset's metadata documents.", 383 accessMode = Schema.AccessMode.READ_ONLY 384 ) 385 private List<DataDescription> dataDescriptions = new ArrayList<>(); 386 387 @Schema( 388 description = "Data language information retrieved from this dataset's metadata documents.", 389 accessMode = Schema.AccessMode.READ_ONLY 390 ) 391 private Language dataLanguage; 392 393 @Schema( 394 description = "Purpose information retrieved from this dataset's metadata documents.", 395 accessMode = Schema.AccessMode.READ_ONLY 396 ) 397 private String purpose; 398 399 @Schema( 400 description = "An overview of the background and context for the dataset.", 401 accessMode = Schema.AccessMode.READ_ONLY 402 ) 403 private String introduction; 404 405 @Schema( 406 description = "A high level overview of interpretation, structure, and content of the dataset.", 407 accessMode = Schema.AccessMode.READ_ONLY 408 ) 409 private String gettingStarted; 410 411 @Schema( 412 description = "Text that acknowledges funders and other key contributors.", 413 accessMode = Schema.AccessMode.READ_ONLY 414 ) 415 private String acknowledgements; 416 417 @Schema( 418 description = "Additional information retrieved from this dataset's metadata documents.", 419 accessMode = Schema.AccessMode.READ_ONLY 420 ) 421 private String additionalInfo; 422 423 @Schema( 424 description = "The publication date retrieved from this dataset's metadata documents.", 425 accessMode = Schema.AccessMode.READ_ONLY 426 ) 427 private Date pubDate; 428 429 @Schema( 430 description = "The maintenance update frequency retrieved from this dataset's metadata documents.", 431 accessMode = Schema.AccessMode.READ_ONLY 432 ) 433 private MaintenanceUpdateFrequency maintenanceUpdateFrequency; 434 435 @Schema( 436 description = "The maintenance description retrieved from this dataset's metadata documents.", 437 accessMode = Schema.AccessMode.READ_ONLY 438 ) 439 private String maintenanceDescription; 440 441 @Schema( 442 description = "The data and metadata license retrieved from this dataset's metadata documents.", 443 accessMode = Schema.AccessMode.READ_ONLY 444 ) 445 private License license; 446 447 @Schema( 448 description = "Basic metadata of the Darwin Core Archive (DwC-A) associated with this dataset.", 449 accessMode = Schema.AccessMode.READ_ONLY 450 ) 451 private DwcA dwca; 452 453 @Override 454 public UUID getKey() { 455 return key; 456 } 457 458 /** 459 * Persisted in the database table. 460 */ 461 @Override 462 public void setKey(UUID key) { 463 this.key = key; 464 } 465 466 @Nullable 467 public String getVersion() { 468 return version; 469 } 470 471 public void setVersion(String version) { 472 this.version = version; 473 } 474 475 @Override 476 public String getTitle() { 477 return title; 478 } 479 480 /** 481 * Persisted in the database table. 482 */ 483 @Override 484 public void setTitle(String title) { 485 this.title = title; 486 } 487 488 @Override 489 @Nullable 490 public String getDescription() { 491 return description; 492 } 493 494 /** 495 * Persisted in the database table. 496 */ 497 @Override 498 public void setDescription(String description) { 499 this.description = description; 500 } 501 502 @Override 503 public Date getCreated() { 504 return created; 505 } 506 507 /** 508 * Autoassigned in the database table, ignored when persisted. 509 */ 510 @Override 511 public void setCreated(Date created) { 512 this.created = created; 513 } 514 515 @Override 516 public Date getModified() { 517 return modified; 518 } 519 520 /** 521 * Persisted in the database table. 522 */ 523 @Override 524 public void setModified(Date modified) { 525 this.modified = modified; 526 } 527 528 @Override 529 @Nullable 530 public Date getDeleted() { 531 return deleted; 532 } 533 534 /** 535 * Persisted in the database table. 536 */ 537 @Override 538 public void setDeleted(Date deleted) { 539 this.deleted = deleted; 540 } 541 542 @Nullable 543 public UUID getParentDatasetKey() { 544 return parentDatasetKey; 545 } 546 547 /** 548 * Persisted in the database table. 549 */ 550 public void setParentDatasetKey(UUID parentDatasetKey) { 551 this.parentDatasetKey = parentDatasetKey; 552 } 553 554 /** 555 * If a dataset is registered with GBIF through more than one place we'll mark all but one as a duplicate by pointing 556 * it to the canonical dataset. That is done using this field. If it is {@code null} then this is not a known 557 * duplicate. 558 */ 559 @Nullable 560 public UUID getDuplicateOfDatasetKey() { 561 return duplicateOfDatasetKey; 562 } 563 564 /** 565 * Persisted in the database table. 566 */ 567 public void setDuplicateOfDatasetKey(UUID duplicateOfDatasetKey) { 568 this.duplicateOfDatasetKey = duplicateOfDatasetKey; 569 } 570 571 @NotNull 572 public UUID getInstallationKey() { 573 return installationKey; 574 } 575 576 /** 577 * Persisted in the database table. 578 */ 579 public void setInstallationKey(UUID installationKey) { 580 this.installationKey = installationKey; 581 } 582 583 @NotNull 584 public UUID getPublishingOrganizationKey() { 585 return publishingOrganizationKey; 586 } 587 588 /** 589 * Persisted in the database table. 590 */ 591 public void setPublishingOrganizationKey(UUID publishingOrganizationKey) { 592 this.publishingOrganizationKey = publishingOrganizationKey; 593 } 594 595 @Nullable 596 public String getPublishingOrganizationName() { 597 return publishingOrganizationName; 598 } 599 600 public void setPublishingOrganizationName(String publishingOrganizationName) { 601 this.publishingOrganizationName = publishingOrganizationName; 602 } 603 604 /** 605 * Networks in which this dataset is a constituent. 606 */ 607 public List<UUID> getNetworkKeys() { 608 return networkKeys; 609 } 610 611 public void setNetworkKeys(List<UUID> networkKeys) { 612 this.networkKeys = networkKeys; 613 } 614 615 /** 616 * Persisted in the database table. 617 * 618 * @return the frequency with which changes are made to the dataset 619 */ 620 @Nullable 621 public MaintenanceUpdateFrequency getMaintenanceUpdateFrequency() { 622 return maintenanceUpdateFrequency; 623 } 624 /** 625 * Persisted in the database table. 626 */ 627 public void setMaintenanceUpdateFrequency(MaintenanceUpdateFrequency maintenanceUpdateFrequency) { 628 this.maintenanceUpdateFrequency = maintenanceUpdateFrequency; 629 } 630 631 /** 632 * A description of the maintenance frequency of this resource. 633 * 634 * @return the description of the maintenance frequency of this resource 635 */ 636 public String getMaintenanceDescription() { 637 return maintenanceDescription; 638 } 639 640 public void setMaintenanceDescription(String maintenanceDescription) { 641 this.maintenanceDescription = maintenanceDescription; 642 } 643 644 /** 645 * Persisted in the database table. 646 * </br> 647 * Note for backwards compatibility, we cannot apply @NotNull to license. Otherwise existing users of our API 648 * would have to ensure Dataset objects always populate license. 649 * </br> 650 * In the Registry DB, Dataset.license defaults to CC-BY 4.0. Therefore license must be excluded from lenientEquals 651 * method. 652 * 653 * @return the License applied to the dataset 654 * 655 * @see <a href="http://dev.gbif.org/issues/browse/POR-3133">POR-3133</a> 656 */ 657 public License getLicense() { 658 return license; 659 } 660 661 /** 662 * Persisted in the database table. Can be interpreted from EML.intellectualRights using machine readable format: 663 * <pre> 664 * {@code 665 * <intellectualRights> 666 * <para>This work is licensed under a <ulink url="http://creativecommons.org/licenses/by/4.0/legalcode"><citetitle>Creative Commons Attribution (CC-BY) 4.0 License</citetitle></ulink>.</para> 667 * </intellectualRights> 668 * } 669 * </pre> 670 */ 671 public void setLicense(License license) { 672 this.license = license; 673 } 674 675 /** 676 * @return the primary DOI for this dataset regardless if issued by GBIF or publisher 677 */ 678 public DOI getDoi() { 679 return doi; 680 } 681 682 public void setDoi(DOI doi) { 683 this.doi = doi; 684 } 685 686 public boolean isExternal() { 687 return external; 688 } 689 690 /** 691 * Persisted in the database table. 692 */ 693 public void setExternal(boolean external) { 694 this.external = external; 695 } 696 697 @Min(0) 698 public int getNumConstituents() { 699 return numConstituents; 700 } 701 702 /** 703 * Not persisted in the database table, but calculated on the fly. 704 */ 705 public void setNumConstituents(int numConstituents) { 706 this.numConstituents = numConstituents; 707 } 708 709 @NotNull 710 public DatasetType getType() { 711 return type; 712 } 713 714 /** 715 * Persisted in the database table. 716 */ 717 public void setType(DatasetType type) { 718 this.type = type; 719 } 720 721 @Nullable 722 public DatasetSubtype getSubtype() { 723 return subtype; 724 } 725 726 /** 727 * Persisted in the database table. 728 */ 729 public void setSubtype(DatasetSubtype subtype) { 730 this.subtype = subtype; 731 } 732 733 @Nullable 734 public String getShortName() { 735 return shortName; 736 } 737 738 public void setShortName(String shortName) { 739 this.shortName = shortName; 740 } 741 742 /** 743 * TODO: Document what this is 744 */ 745 @Nullable 746 @Size(min = 2, max = 50) 747 public String getAlias() { 748 return alias; 749 } 750 751 /** 752 * Persisted in the database table. 753 */ 754 public void setAlias(String alias) { 755 this.alias = alias; 756 } 757 758 /** 759 * TODO: Document what this is 760 * TODO: are both alias & abbreviation needed? 761 */ 762 @Nullable 763 @Size(min = 1, max = 50) 764 public String getAbbreviation() { 765 return abbreviation; 766 } 767 768 /** 769 * Persisted in the database table. 770 */ 771 public void setAbbreviation(String abbreviation) { 772 this.abbreviation = abbreviation; 773 } 774 775 @NotNull 776 public Language getLanguage() { 777 return language; 778 } 779 780 /** 781 * Persisted in the database table. 782 */ 783 public void setLanguage(Language language) { 784 this.language = language; 785 } 786 787 @HttpURI 788 @Nullable 789 public URI getHomepage() { 790 return homepage; 791 } 792 793 /** 794 * Persisted in the database table. 795 */ 796 public void setHomepage(URI homepage) { 797 this.homepage = homepage; 798 } 799 800 @HttpURI 801 @Nullable 802 public URI getLogoUrl() { 803 return logoUrl; 804 } 805 806 /** 807 * Persisted in the database table. 808 */ 809 public void setLogoUrl(URI logoUrl) { 810 this.logoUrl = logoUrl; 811 } 812 813 /** 814 * The exact form of how to cite this dataset. 815 */ 816 @Nullable 817 @Valid 818 public Citation getCitation() { 819 return citation; 820 } 821 822 /** 823 * Persisted in the database table. 824 */ 825 public void setCitation(Citation citation) { 826 this.citation = citation; 827 } 828 829 /** 830 * A generated list of contacts used in the citation text when it is generated by the GBIF API. 831 */ 832 @Nullable 833 public List<CitationContact> getContactsCitation() { 834 return contactsCitation; 835 } 836 837 public void setContactsCitation(List<CitationContact> contactsCitation) { 838 this.contactsCitation = contactsCitation; 839 } 840 841 /** 842 * Any kind of (copy)rights/IPR statements that apply to the datasets data. 843 */ 844 @Nullable 845 @Size(min = 1) 846 public String getRights() { 847 return rights; 848 } 849 850 /** 851 * Persisted in the database table. 852 */ 853 public void setRights(String rights) { 854 this.rights = rights; 855 } 856 857 public boolean isLockedForAutoUpdate() { 858 return lockedForAutoUpdate; 859 } 860 861 /** 862 * Persisted in the database table. 863 */ 864 public void setLockedForAutoUpdate(boolean lockedForAutoUpdate) { 865 this.lockedForAutoUpdate = lockedForAutoUpdate; 866 } 867 868 @Override 869 public String getCreatedBy() { 870 return createdBy; 871 } 872 873 /** 874 * Persisted in the database table. 875 */ 876 @Override 877 public void setCreatedBy(String createdBy) { 878 this.createdBy = createdBy; 879 } 880 881 @Override 882 public String getModifiedBy() { 883 return modifiedBy; 884 } 885 886 /** 887 * Persisted in the database table. 888 */ 889 @Override 890 public void setModifiedBy(String modifiedBy) { 891 this.modifiedBy = modifiedBy; 892 } 893 894 @Override 895 public List<Contact> getContacts() { 896 return contacts; 897 } 898 899 @Override 900 public void setContacts(List<Contact> contacts) { 901 this.contacts = contacts; 902 } 903 904 @Override 905 public List<Endpoint> getEndpoints() { 906 return endpoints; 907 } 908 909 @Override 910 public void setEndpoints(List<Endpoint> endpoints) { 911 this.endpoints = endpoints; 912 } 913 914 @Override 915 public void addEndpoint(Endpoint endpoint) { 916 endpoints.add(endpoint); 917 } 918 919 @Override 920 public List<MachineTag> getMachineTags() { 921 return machineTags; 922 } 923 924 @Override 925 public void setMachineTags(List<MachineTag> machineTags) { 926 this.machineTags = machineTags; 927 } 928 929 @Override 930 public void addMachineTag(MachineTag machineTag) { 931 machineTags.add(machineTag); 932 } 933 934 @Override 935 public List<Tag> getTags() { 936 return tags; 937 } 938 939 @Override 940 public void setTags(List<Tag> tags) { 941 this.tags = tags; 942 } 943 944 @Override 945 public List<Identifier> getIdentifiers() { 946 return identifiers; 947 } 948 949 @Override 950 public void setIdentifiers(List<Identifier> identifiers) { 951 this.identifiers = identifiers; 952 } 953 954 @Override 955 public List<Comment> getComments() { 956 return comments; 957 } 958 959 @Override 960 public void setComments(List<Comment> comments) { 961 this.comments = comments; 962 } 963 964 public List<Citation> getBibliographicCitations() { 965 return bibliographicCitations; 966 } 967 968 public void setBibliographicCitations(List<Citation> bibliographicCitations) { 969 this.bibliographicCitations = bibliographicCitations; 970 } 971 972 public List<CuratorialUnitComposite> getCuratorialUnits() { 973 return curatorialUnits; 974 } 975 976 public void setCuratorialUnits(List<CuratorialUnitComposite> curatorialUnits) { 977 this.curatorialUnits = curatorialUnits; 978 } 979 980 public List<TaxonomicCoverages> getTaxonomicCoverages() { 981 return taxonomicCoverages; 982 } 983 984 public void setTaxonomicCoverages(List<TaxonomicCoverages> taxonomicCoverages) { 985 this.taxonomicCoverages = taxonomicCoverages; 986 } 987 988 public String getGeographicCoverageDescription() { 989 return geographicCoverageDescription; 990 } 991 992 public void setGeographicCoverageDescription(String geographicCoverageDescription) { 993 this.geographicCoverageDescription = geographicCoverageDescription; 994 } 995 996 public List<GeospatialCoverage> getGeographicCoverages() { 997 return geographicCoverages; 998 } 999 1000 public void setGeographicCoverages(List<GeospatialCoverage> geographicCoverages) { 1001 this.geographicCoverages = geographicCoverages; 1002 } 1003 1004 public List<TemporalCoverage> getTemporalCoverages() { 1005 return temporalCoverages; 1006 } 1007 1008 public void setTemporalCoverages(List<TemporalCoverage> temporalCoverages) { 1009 this.temporalCoverages = temporalCoverages; 1010 } 1011 1012 public List<KeywordCollection> getKeywordCollections() { 1013 return keywordCollections; 1014 } 1015 1016 public void setKeywordCollections(List<KeywordCollection> keywordCollections) { 1017 this.keywordCollections = keywordCollections; 1018 } 1019 1020 public Project getProject() { 1021 return project; 1022 } 1023 1024 public void setProject(Project project) { 1025 this.project = project; 1026 } 1027 1028 public SamplingDescription getSamplingDescription() { 1029 return samplingDescription; 1030 } 1031 1032 public void setSamplingDescription(SamplingDescription samplingDescription) { 1033 this.samplingDescription = samplingDescription; 1034 } 1035 1036 public Set<Country> getCountryCoverage() { 1037 return countryCoverage; 1038 } 1039 1040 public void setCountryCoverage(Set<Country> countryCoverage) { 1041 this.countryCoverage = countryCoverage; 1042 } 1043 1044 public List<Collection> getCollections() { 1045 return collections; 1046 } 1047 1048 public void setCollections(List<Collection> collections) { 1049 this.collections = collections; 1050 } 1051 1052 public List<DataDescription> getDataDescriptions() { 1053 return dataDescriptions; 1054 } 1055 1056 public void setDataDescriptions(List<DataDescription> dataDescriptions) { 1057 this.dataDescriptions = dataDescriptions; 1058 } 1059 1060 public Language getDataLanguage() { 1061 return dataLanguage; 1062 } 1063 1064 public void setDataLanguage(Language dataLanguage) { 1065 this.dataLanguage = dataLanguage; 1066 } 1067 1068 public String getPurpose() { 1069 return purpose; 1070 } 1071 1072 public void setPurpose(String purpose) { 1073 this.purpose = purpose; 1074 } 1075 1076 @Nullable 1077 public String getIntroduction() { 1078 return introduction; 1079 } 1080 1081 public void setIntroduction(String introduction) { 1082 this.introduction = introduction; 1083 } 1084 1085 @Nullable 1086 public String getGettingStarted() { 1087 return gettingStarted; 1088 } 1089 1090 public void setGettingStarted(String gettingStarted) { 1091 this.gettingStarted = gettingStarted; 1092 } 1093 1094 @Nullable 1095 public String getAcknowledgements() { 1096 return acknowledgements; 1097 } 1098 1099 public void setAcknowledgements(String acknowledgements) { 1100 this.acknowledgements = acknowledgements; 1101 } 1102 1103 public String getAdditionalInfo() { 1104 return additionalInfo; 1105 } 1106 1107 public void setAdditionalInfo(String additionalInfo) { 1108 this.additionalInfo = additionalInfo; 1109 } 1110 1111 public Date getPubDate() { 1112 return pubDate; 1113 } 1114 1115 public void setPubDate(Date pubDate) { 1116 this.pubDate = pubDate; 1117 } 1118 1119 @Nullable 1120 @Valid 1121 public DwcA getDwca() { 1122 return dwca; 1123 } 1124 1125 public void setDwca(DwcA dwca) { 1126 this.dwca = dwca; 1127 } 1128 1129 @Override 1130 public boolean equals(Object o) { 1131 if (this == o) { 1132 return true; 1133 } 1134 if (o == null || getClass() != o.getClass()) { 1135 return false; 1136 } 1137 Dataset dataset = (Dataset) o; 1138 return external == dataset.external 1139 && numConstituents == dataset.numConstituents 1140 && lockedForAutoUpdate == dataset.lockedForAutoUpdate 1141 && Objects.equals(key, dataset.key) 1142 && Objects.equals(parentDatasetKey, dataset.parentDatasetKey) 1143 && Objects.equals(duplicateOfDatasetKey, dataset.duplicateOfDatasetKey) 1144 && Objects.equals(installationKey, dataset.installationKey) 1145 && Objects.equals(publishingOrganizationKey, dataset.publishingOrganizationKey) 1146 && Objects.equals(publishingOrganizationName, dataset.publishingOrganizationName) 1147 && Objects.equals(networkKeys, dataset.networkKeys) 1148 && Objects.equals(doi, dataset.doi) 1149 && Objects.equals(version, dataset.version) 1150 && type == dataset.type 1151 && subtype == dataset.subtype 1152 && Objects.equals(shortName, dataset.shortName) 1153 && Objects.equals(title, dataset.title) 1154 && Objects.equals(alias, dataset.alias) 1155 && Objects.equals(abbreviation, dataset.abbreviation) 1156 && Objects.equals(description, dataset.description) 1157 && language == dataset.language 1158 && Objects.equals(homepage, dataset.homepage) 1159 && Objects.equals(logoUrl, dataset.logoUrl) 1160 && Objects.equals(citation, dataset.citation) 1161 && Objects.equals(contactsCitation, dataset.contactsCitation) 1162 && Objects.equals(rights, dataset.rights) 1163 && Objects.equals(createdBy, dataset.createdBy) 1164 && Objects.equals(modifiedBy, dataset.modifiedBy) 1165 && Objects.equals(created, dataset.created) 1166 && Objects.equals(modified, dataset.modified) 1167 && Objects.equals(deleted, dataset.deleted) 1168 && Objects.equals(contacts, dataset.contacts) 1169 && Objects.equals(endpoints, dataset.endpoints) 1170 && Objects.equals(machineTags, dataset.machineTags) 1171 && Objects.equals(tags, dataset.tags) 1172 && Objects.equals(identifiers, dataset.identifiers) 1173 && Objects.equals(comments, dataset.comments) 1174 && Objects.equals(bibliographicCitations, dataset.bibliographicCitations) 1175 && Objects.equals(curatorialUnits, dataset.curatorialUnits) 1176 && Objects.equals(taxonomicCoverages, dataset.taxonomicCoverages) 1177 && Objects.equals(geographicCoverageDescription, dataset.geographicCoverageDescription) 1178 && Objects.equals(geographicCoverages, dataset.geographicCoverages) 1179 && Objects.equals(temporalCoverages, dataset.temporalCoverages) 1180 && Objects.equals(keywordCollections, dataset.keywordCollections) 1181 && Objects.equals(project, dataset.project) 1182 && Objects.equals(samplingDescription, dataset.samplingDescription) 1183 && Objects.equals(countryCoverage, dataset.countryCoverage) 1184 && Objects.equals(collections, dataset.collections) 1185 && Objects.equals(dataDescriptions, dataset.dataDescriptions) 1186 && dataLanguage == dataset.dataLanguage 1187 && Objects.equals(purpose, dataset.purpose) 1188 && Objects.equals(introduction, dataset.introduction) 1189 && Objects.equals(gettingStarted, dataset.gettingStarted) 1190 && Objects.equals(acknowledgements, dataset.acknowledgements) 1191 && Objects.equals(additionalInfo, dataset.additionalInfo) 1192 && Objects.equals(pubDate, dataset.pubDate) 1193 && maintenanceUpdateFrequency == dataset.maintenanceUpdateFrequency 1194 && Objects.equals(maintenanceDescription, dataset.maintenanceDescription) 1195 && license == dataset.license 1196 && Objects.equals(dwca, dataset.dwca); 1197 } 1198 1199 @Override 1200 public int hashCode() { 1201 return Objects.hash( 1202 key, 1203 parentDatasetKey, 1204 duplicateOfDatasetKey, 1205 installationKey, 1206 publishingOrganizationKey, 1207 publishingOrganizationName, 1208 networkKeys, 1209 doi, 1210 version, 1211 external, 1212 numConstituents, 1213 type, 1214 subtype, 1215 shortName, 1216 title, 1217 alias, 1218 abbreviation, 1219 description, 1220 language, 1221 homepage, 1222 logoUrl, 1223 citation, 1224 contactsCitation, 1225 rights, 1226 lockedForAutoUpdate, 1227 createdBy, 1228 modifiedBy, 1229 created, 1230 modified, 1231 deleted, 1232 contacts, 1233 endpoints, 1234 machineTags, 1235 tags, 1236 identifiers, 1237 comments, 1238 bibliographicCitations, 1239 curatorialUnits, 1240 taxonomicCoverages, 1241 geographicCoverageDescription, 1242 geographicCoverages, 1243 temporalCoverages, 1244 keywordCollections, 1245 project, 1246 samplingDescription, 1247 countryCoverage, 1248 collections, 1249 dataDescriptions, 1250 dataLanguage, 1251 purpose, 1252 introduction, 1253 gettingStarted, 1254 acknowledgements, 1255 additionalInfo, 1256 pubDate, 1257 maintenanceUpdateFrequency, 1258 maintenanceDescription, 1259 license, 1260 dwca); 1261 } 1262 1263 @Override 1264 public String toString() { 1265 return new StringJoiner(", ", Dataset.class.getSimpleName() + "[", "]") 1266 .add("key=" + key) 1267 .add("parentDatasetKey=" + parentDatasetKey) 1268 .add("duplicateOfDatasetKey=" + duplicateOfDatasetKey) 1269 .add("installationKey=" + installationKey) 1270 .add("publishingOrganizationKey=" + publishingOrganizationKey) 1271 .add("publishingOrganizationName=" + publishingOrganizationName) 1272 .add("networkKeys=" + networkKeys) 1273 .add("doi=" + doi) 1274 .add("version='" + version + "'") 1275 .add("external=" + external) 1276 .add("numConstituents=" + numConstituents) 1277 .add("type=" + type) 1278 .add("subtype=" + subtype) 1279 .add("shortName='" + shortName + "'") 1280 .add("title='" + title + "'") 1281 .add("alias='" + alias + "'") 1282 .add("abbreviation='" + abbreviation + "'") 1283 .add("description='" + description + "'") 1284 .add("language=" + language) 1285 .add("homepage=" + homepage) 1286 .add("logoUrl=" + logoUrl) 1287 .add("citation=" + citation) 1288 .add("contactsCitation=" + contactsCitation) 1289 .add("rights='" + rights + "'") 1290 .add("lockedForAutoUpdate=" + lockedForAutoUpdate) 1291 .add("createdBy='" + createdBy + "'") 1292 .add("modifiedBy='" + modifiedBy + "'") 1293 .add("created=" + created) 1294 .add("modified=" + modified) 1295 .add("deleted=" + deleted) 1296 .add("contacts=" + contacts) 1297 .add("endpoints=" + endpoints) 1298 .add("machineTags=" + machineTags) 1299 .add("tags=" + tags) 1300 .add("identifiers=" + identifiers) 1301 .add("comments=" + comments) 1302 .add("bibliographicCitations=" + bibliographicCitations) 1303 .add("curatorialUnits=" + curatorialUnits) 1304 .add("taxonomicCoverages=" + taxonomicCoverages) 1305 .add("geographicCoverageDescription='" + geographicCoverageDescription + "'") 1306 .add("geographicCoverages=" + geographicCoverages) 1307 .add("temporalCoverages=" + temporalCoverages) 1308 .add("keywordCollections=" + keywordCollections) 1309 .add("project=" + project) 1310 .add("samplingDescription=" + samplingDescription) 1311 .add("countryCoverage=" + countryCoverage) 1312 .add("collections=" + collections) 1313 .add("dataDescriptions=" + dataDescriptions) 1314 .add("dataLanguage=" + dataLanguage) 1315 .add("purpose='" + purpose + "'") 1316 .add("introduction='" + introduction + "'") 1317 .add("gettingStarted='" + gettingStarted + "'") 1318 .add("acknowledgements='" + acknowledgements + "'") 1319 .add("additionalInfo='" + additionalInfo + "'") 1320 .add("pubDate=" + pubDate) 1321 .add("maintenanceUpdateFrequency=" + maintenanceUpdateFrequency) 1322 .add("maintenanceDescription='" + maintenanceDescription + "'") 1323 .add("license=" + license) 1324 .add("dwca=" + dwca) 1325 .toString(); 1326 } 1327 1328 /** 1329 * Only checks the persisted properties, excluding the server controlled fields (key, created, license etc). 1330 * Does not include the nested properties. 1331 */ 1332 @Override 1333 public boolean lenientEquals(Dataset other) { 1334 if (this == other) { 1335 return true; 1336 } 1337 return Objects.equals(this.parentDatasetKey, other.parentDatasetKey) 1338 && Objects.equals(this.duplicateOfDatasetKey, other.duplicateOfDatasetKey) 1339 && Objects.equals(this.installationKey, other.installationKey) 1340 && Objects.equals(this.publishingOrganizationKey, other.publishingOrganizationKey) 1341 && Objects.equals(this.publishingOrganizationName, other.publishingOrganizationName) 1342 && Objects.equals(this.doi, other.doi) 1343 && Objects.equals(this.external, other.external) 1344 && Objects.equals(this.type, other.type) 1345 && Objects.equals(this.subtype, other.subtype) 1346 && Objects.equals(this.title, other.title) 1347 && Objects.equals(this.alias, other.alias) 1348 && Objects.equals(this.abbreviation, other.abbreviation) 1349 && Objects.equals(this.description, other.description) 1350 && Objects.equals(this.language, other.language) 1351 && Objects.equals(this.homepage, other.homepage) 1352 && Objects.equals(this.logoUrl, other.logoUrl) 1353 && Objects.equals(this.citation, other.citation) 1354 && Objects.equals(this.rights, other.rights) 1355 && Objects.equals(this.lockedForAutoUpdate, other.lockedForAutoUpdate) 1356 && Objects.equals(this.deleted, other.deleted) 1357 && Objects.equals(this.maintenanceUpdateFrequency, other.maintenanceUpdateFrequency) 1358 && Objects.equals(this.maintenanceDescription, other.maintenanceDescription) 1359 && Objects.equals(this.dwca, other.dwca); 1360 } 1361 1362 /** 1363 * Metadata of dataset that has been published as a Darwin Core Archive (DwC-A). 1364 */ 1365 @NoArgsConstructor 1366 @Data 1367 public static class DwcA { 1368 @Schema( 1369 description = "This attribute, within the <core>, indicates the specific " + 1370 "type of data being represented in the core data file.**." 1371 ) 1372 private String coreType; 1373 1374 @Schema( 1375 description = "This attribute, within the <extensions>, indicates the specific " + 1376 "type of data being represented in the associated extension data file.**." 1377 ) 1378 private List<String> extensions; 1379 1380 @Schema( 1381 description = "Timestamp of when the dataset was modified.", 1382 accessMode = Schema.AccessMode.READ_ONLY 1383 ) 1384 @Null(groups = {PrePersist.class}) 1385 private Date modified; 1386 1387 1388 public String getCoreType() { 1389 return coreType; 1390 } 1391 1392 public void setCoreType(String coreType) { 1393 this.coreType = coreType; 1394 } 1395 1396 @Nullable 1397 public List<String> getExtensions() { 1398 return extensions; 1399 } 1400 1401 public void setExtensions(List<String> extensions) { 1402 this.extensions = extensions; 1403 } 1404 1405 @Nullable 1406 public Date getModified() { 1407 return modified; 1408 } 1409 1410 public void setModified(Date modified) { 1411 this.modified = modified; 1412 } 1413 } 1414}