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.collections; 015 016import lombok.Getter; 017 018import lombok.Setter; 019 020import org.gbif.api.model.registry.Comment; 021import org.gbif.api.model.registry.Identifier; 022import org.gbif.api.model.registry.LenientEquals; 023import org.gbif.api.model.registry.MachineTag; 024import org.gbif.api.model.registry.PrePersist; 025import org.gbif.api.model.registry.Tag; 026import org.gbif.api.util.HttpURI; 027import org.gbif.api.util.LenientEqualsUtils; 028import org.gbif.api.util.validators.email.ValidEmail; 029import org.gbif.api.vocabulary.License; 030import org.gbif.api.vocabulary.collections.MasterSourceType; 031 032import java.math.BigDecimal; 033import java.net.URI; 034import java.util.ArrayList; 035import java.util.Date; 036import java.util.List; 037import java.util.Objects; 038import java.util.UUID; 039 040import javax.annotation.Nullable; 041import javax.validation.Valid; 042import javax.validation.constraints.NotNull; 043import javax.validation.constraints.Size; 044 045import com.fasterxml.jackson.annotation.JsonIgnore; 046 047import io.swagger.v3.oas.annotations.Hidden; 048import io.swagger.v3.oas.annotations.media.Schema; 049import lombok.EqualsAndHashCode; 050import lombok.ToString; 051 052/** 053 * The owner or location of collection. Usually an established organization or foundation, 054 * especially one dedicated to education, public service, or culture. 055 */ 056@SuppressWarnings("unused") 057@ToString 058@EqualsAndHashCode 059public class Institution implements CollectionEntity, LenientEquals<Institution> { 060 061 @Schema( 062 description = "Unique GBIF key for the institution.", 063 accessMode = Schema.AccessMode.READ_ONLY) 064 private UUID key; 065 066 @Schema( 067 description = 068 "Code used to identify the institution.\n\n" + "*(NB Not required for updates.)*") 069 @Sourceable(masterSources = MasterSourceType.IH) 070 private String code; 071 072 @Schema( 073 description = "Name or title of the institution.\n\n" + "*(NB Not required for updates.)*") 074 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 075 private String name; 076 077 @Schema(description = "Description of the institution.") 078 @Sourceable(masterSources = MasterSourceType.GBIF_REGISTRY) 079 private String description; 080 081 @Setter 082 @Getter 083 @Schema(description = "Types of the institution, describing its main activities.") 084 private List<String> types = new ArrayList<>(); 085 086 @Schema(description = "Whether the institution is active or operational.") 087 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 088 private boolean active; 089 090 @Schema(description = "Email addresses associated with the institution.") 091 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 092 private List<@ValidEmail String> email = new ArrayList<>(); 093 094 @Schema(description = "Telephone numbers associated with the instutiton.") 095 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 096 private List<String> phone = new ArrayList<>(); 097 098 @Setter 099 @Schema(description = "The institution's WWW homepage.") 100 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 101 private URI homepage; 102 103 @Setter 104 @Schema(description = "URLs for the main interactive catalogues of the institution.") 105 private List<@HttpURI URI> catalogUrls = new ArrayList<>(); 106 107 @Setter 108 @Schema(description = "URLs for machine-readable APIs for the institution catalogues.") 109 private List<@HttpURI URI> apiUrls = new ArrayList<>(); 110 111 @Setter 112 @Getter 113 @Schema( 114 description = 115 "The mechanisms, processes and relations by which an " 116 + "institution is controlled and directed.") 117 private List<String> institutionalGovernances = new ArrayList<>(); 118 119 @Setter 120 @Getter 121 @Schema( 122 description = 123 "The academic or research disciplines to which an " + "institution is dedicated.") 124 private List<String> disciplines = new ArrayList<>(); 125 126 @Setter 127 @Getter 128 @Schema(description = "The latitude of the institution.") 129 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 130 private BigDecimal latitude; 131 132 @Setter 133 @Getter 134 @Schema(description = "The longitude of the institution.") 135 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 136 private BigDecimal longitude; 137 138 @Schema(description = "The postal address of the institution.") 139 @Sourceable(masterSources = MasterSourceType.IH) 140 private Address mailingAddress; 141 142 @Schema(description = "The address of the location of the institution.") 143 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 144 private Address address; 145 146 @Setter 147 @Getter 148 @Schema(description = "Additional names by which the institution is known.") 149 private List<String> additionalNames = new ArrayList<>(); 150 151 @Setter 152 @Getter 153 @Schema(description = "The date the institution was founded or established.") 154 @Sourceable(masterSources = MasterSourceType.IH) 155 private Integer foundingDate; 156 157 @Setter 158 @Getter 159 @Schema(description = "An estimate of the number of specimens hosted by the institution.") 160 private Integer numberSpecimens; 161 162 @Setter 163 @Schema(description = "A URL to a logo for the institution.") 164 @Sourceable(masterSources = MasterSourceType.GBIF_REGISTRY) 165 private URI logoUrl; 166 167 @Schema( 168 description = 169 "The GBIF username of the creator of the institution entity in " + "the GBIF registry.", 170 accessMode = Schema.AccessMode.READ_ONLY) 171 private String createdBy; 172 173 @Schema( 174 description = 175 "The GBIF username of the last user to modify the institution " 176 + "entity in the GBIF registry.", 177 accessMode = Schema.AccessMode.READ_ONLY) 178 private String modifiedBy; 179 180 @Schema( 181 description = 182 "Timestamp of when the institution entity was created in the GBIF " + "registry.", 183 accessMode = Schema.AccessMode.READ_ONLY) 184 private Date created; 185 186 @Schema( 187 description = 188 "Timestamp of when the institution entity was modified in the GBIF " + "registry.", 189 accessMode = Schema.AccessMode.READ_ONLY) 190 private Date modified; 191 192 @Schema( 193 description = 194 "If present, the institution was deleted at this time. " 195 + "It is possible for it to be restored in the future.", 196 accessMode = Schema.AccessMode.READ_ONLY) 197 private Date deleted; 198 199 @Schema( 200 description = "A list of tags associated with this institution.", 201 accessMode = Schema.AccessMode.READ_ONLY) 202 private List<Tag> tags = new ArrayList<>(); 203 204 @Schema( 205 description = "A list of identifiers associated with this institution.", 206 accessMode = Schema.AccessMode.READ_ONLY) 207 @Sourceable(masterSources = MasterSourceType.IH, sourceableParts = "IH_IRN") 208 private List<Identifier> identifiers = new ArrayList<>(); 209 210 @Schema(description = "A list of contact people for this institution.") 211 @Sourceable(masterSources = {MasterSourceType.GBIF_REGISTRY, MasterSourceType.IH}) 212 private List<Contact> contactPersons = new ArrayList<>(); 213 214 @Schema( 215 description = "A list of machine tags associated with this institution.", 216 accessMode = Schema.AccessMode.READ_ONLY) 217 private List<MachineTag> machineTags = new ArrayList<>(); 218 219 @Schema(description = "Alternative codes for this institution.") 220 private List<AlternativeCode> alternativeCodes = new ArrayList<>(); 221 222 @Schema( 223 description = "A list of comments associated with this institution.", 224 accessMode = Schema.AccessMode.READ_ONLY) 225 private List<Comment> comments = new ArrayList<>(); 226 227 @Schema( 228 description = "Mapping of a GRSciColl institution to occurrence records", 229 accessMode = Schema.AccessMode.READ_ONLY) 230 private List<OccurrenceMapping> occurrenceMappings = new ArrayList<>(); 231 232 @Schema(description = "A collection record that replaces this collection.") 233 private UUID replacedBy; 234 235 @Setter 236 @Getter 237 @Schema( 238 description = 239 "Indicates if the institution was converted to a collection and specifies the UUID key of that collection") 240 private UUID convertedToCollection; 241 242 @Schema(description = "The primary source of this institution record.") 243 private MasterSourceType masterSource; 244 245 @Schema( 246 description = 247 "Information to assist the synchronization of the master source " 248 + "record with the record in the GBIF registry.") 249 private MasterSourceMetadata masterSourceMetadata; 250 251 @Schema(description = "Whether the institution is shown on the NHC portal.") 252 private Boolean displayOnNHCPortal; 253 254 @Setter 255 @Getter 256 @Schema(description = "An estimate of the number of occurrences linked to the institution.") 257 private Integer occurrenceCount; 258 259 @Setter 260 @Getter 261 @Schema(description = "An estimate of the number of type specimens linked to the institution.") 262 private Integer typeSpecimenCount; 263 264 @Schema( 265 description = 266 "URI to the image to be featured on the institution page, this image should be associated with a license.") 267 private URI featuredImageUrl; 268 269 @Schema( 270 description = "The license associated with the image to be featured on the institution page.") 271 private License featuredImageLicense; 272 273 @Schema( 274 description = " Information about ownership, attribution, etc. of the featured image. This value with " 275 + "be used to generate a suggested citation of the image." 276 ) 277 private String featuredImageAttribution; 278 279 /** GBIF unique identifier. */ 280 @Override 281 public UUID getKey() { 282 return key; 283 } 284 285 @Override 286 public void setKey(UUID key) { 287 this.key = key; 288 } 289 290 /** Code used to identify the collection. */ 291 @NotNull(groups = PrePersist.class) 292 @Override 293 public String getCode() { 294 return code; 295 } 296 297 @Override 298 public void setCode(String code) { 299 this.code = code; 300 } 301 302 /** Name or title of an institution. */ 303 @NotNull 304 @Override 305 public String getName() { 306 return name; 307 } 308 309 @Override 310 public void setName(String name) { 311 this.name = name; 312 } 313 314 /** Textual description of institution. */ 315 @Nullable 316 @Size(min = 1) 317 @Override 318 public String getDescription() { 319 return description; 320 } 321 322 @Override 323 public void setDescription(String description) { 324 this.description = description; 325 } 326 327 /** Is the institution active/operational?. */ 328 @Override 329 public boolean isActive() { 330 return active; 331 } 332 333 @Override 334 public void setActive(boolean active) { 335 this.active = active; 336 } 337 338 @Override 339 public List<String> getEmail() { 340 return email; 341 } 342 343 @Override 344 public void setEmail(List<String> email) { 345 this.email = email; 346 } 347 348 @Override 349 public List<String> getPhone() { 350 return phone; 351 } 352 353 @Override 354 public void setPhone(List<String> phone) { 355 this.phone = phone; 356 } 357 358 /** URL to the home page of an institution. */ 359 @HttpURI 360 @Nullable 361 public URI getHomepage() { 362 return homepage; 363 } 364 365 /** URL to the main catalogue of an institution. */ 366 @Nullable 367 public List<URI> getCatalogUrls() { 368 return catalogUrls; 369 } 370 371 /** Machine-consumable endpoint of an institution and probably its collections. */ 372 @Nullable 373 public List<URI> getApiUrls() { 374 return apiUrls; 375 } 376 377 @Nullable 378 @Valid 379 @Override 380 public Address getMailingAddress() { 381 return mailingAddress; 382 } 383 384 @Override 385 public void setMailingAddress(Address mailingAddress) { 386 this.mailingAddress = mailingAddress; 387 } 388 389 @Nullable 390 @Valid 391 @Override 392 public Address getAddress() { 393 return address; 394 } 395 396 @Override 397 public void setAddress(Address address) { 398 this.address = address; 399 } 400 401 /** Logo/Image that identifies the institution. */ 402 @HttpURI 403 @Nullable 404 public URI getLogoUrl() { 405 return logoUrl; 406 } 407 408 @Override 409 public String getCreatedBy() { 410 return createdBy; 411 } 412 413 @Override 414 public void setCreatedBy(String createdBy) { 415 this.createdBy = createdBy; 416 } 417 418 @Override 419 public String getModifiedBy() { 420 return modifiedBy; 421 } 422 423 @Override 424 public void setModifiedBy(String modifiedBy) { 425 this.modifiedBy = modifiedBy; 426 } 427 428 @Override 429 public Date getCreated() { 430 return created; 431 } 432 433 @Override 434 public void setCreated(Date created) { 435 this.created = created; 436 } 437 438 @Override 439 public Date getModified() { 440 return modified; 441 } 442 443 @Override 444 public void setModified(Date modified) { 445 this.modified = modified; 446 } 447 448 @Override 449 public Date getDeleted() { 450 return deleted; 451 } 452 453 @Override 454 public void setDeleted(Date deleted) { 455 this.deleted = deleted; 456 } 457 458 @Override 459 public List<Identifier> getIdentifiers() { 460 return identifiers; 461 } 462 463 @Override 464 public void setIdentifiers(List<Identifier> identifiers) { 465 this.identifiers = identifiers; 466 } 467 468 @Override 469 public List<Tag> getTags() { 470 return tags; 471 } 472 473 @Override 474 public void setTags(List<Tag> tags) { 475 this.tags = tags; 476 } 477 478 @Valid 479 @Override 480 public List<Contact> getContactPersons() { 481 return contactPersons; 482 } 483 484 @Override 485 public void setContactPersons(List<Contact> contactPersons) { 486 this.contactPersons = contactPersons; 487 } 488 489 @Override 490 public @NotNull List<MachineTag> getMachineTags() { 491 return machineTags; 492 } 493 494 @Override 495 public void setMachineTags(List<MachineTag> machineTags) { 496 this.machineTags = machineTags; 497 } 498 499 @Override 500 public void addMachineTag(MachineTag machineTag) { 501 this.machineTags.add(machineTag); 502 } 503 504 /** Alternative codes for an institution. */ 505 @Override 506 public List<AlternativeCode> getAlternativeCodes() { 507 return alternativeCodes; 508 } 509 510 @Override 511 public void setAlternativeCodes(List<AlternativeCode> alternativeCodes) { 512 this.alternativeCodes = alternativeCodes; 513 } 514 515 @Override 516 public List<Comment> getComments() { 517 return comments; 518 } 519 520 @Override 521 public void setComments(List<Comment> comments) { 522 this.comments = comments; 523 } 524 525 @Override 526 public List<OccurrenceMapping> getOccurrenceMappings() { 527 return occurrenceMappings; 528 } 529 530 @Override 531 public void setOccurrenceMappings(List<OccurrenceMapping> occurrenceMappings) { 532 this.occurrenceMappings = occurrenceMappings; 533 } 534 535 @Override 536 public UUID getReplacedBy() { 537 return replacedBy; 538 } 539 540 @Override 541 public void setReplacedBy(UUID replacedBy) { 542 this.replacedBy = replacedBy; 543 } 544 545 @Override 546 public MasterSourceType getMasterSource() { 547 return masterSource; 548 } 549 550 @Override 551 public void setMasterSource(MasterSourceType masterSource) { 552 this.masterSource = masterSource; 553 } 554 555 @Override 556 public MasterSourceMetadata getMasterSourceMetadata() { 557 return masterSourceMetadata; 558 } 559 560 @Override 561 public void setMasterSourceMetadata(MasterSourceMetadata masterSourceMetadata) { 562 this.masterSourceMetadata = masterSourceMetadata; 563 } 564 565 @Override 566 public Boolean getDisplayOnNHCPortal() { 567 return displayOnNHCPortal; 568 } 569 570 @Override 571 public void setDisplayOnNHCPortal(Boolean displayOnNHCPortal) { 572 this.displayOnNHCPortal = displayOnNHCPortal; 573 } 574 575 @HttpURI 576 @Nullable 577 @Override 578 public URI getFeaturedImageUrl() { 579 return featuredImageUrl; 580 } 581 582 @Override 583 public void setFeaturedImageUrl(URI featuredImageUrl) { 584 this.featuredImageUrl = featuredImageUrl; 585 } 586 587 @Nullable 588 @Override 589 public License getFeaturedImageLicense() { 590 return featuredImageLicense; 591 } 592 593 @Override 594 public void setFeaturedImageLicense(License featuredImageLicense) { 595 this.featuredImageLicense = featuredImageLicense; 596 } 597 598 @Nullable 599 @Override 600 public String getFeaturedImageAttribution() { 601 return featuredImageAttribution; 602 } 603 604 @Override 605 public void setFeaturedImageAttribution(String featuredImageAttribution) { 606 this.featuredImageAttribution = featuredImageAttribution; 607 } 608 609 @Hidden 610 @JsonIgnore 611 public String getCountry() { 612 if (address != null && address.getCountry() != null) { 613 return address.getCountry().getIso2LetterCode(); 614 } else if (mailingAddress != null && mailingAddress.getCountry() != null) { 615 return mailingAddress.getCountry().getIso2LetterCode(); 616 } 617 return null; 618 } 619 620 @Hidden 621 @JsonIgnore 622 public String getCity() { 623 if (address != null && address.getCity() != null) { 624 return address.getCity(); 625 } else if (mailingAddress != null && mailingAddress.getCity() != null) { 626 return mailingAddress.getCity(); 627 } 628 return null; 629 } 630 631 @Hidden 632 @JsonIgnore 633 public String getProvince() { 634 if (address != null && address.getProvince() != null) { 635 return address.getProvince(); 636 } else if (mailingAddress != null && mailingAddress.getProvince() != null) { 637 return mailingAddress.getProvince(); 638 } 639 return null; 640 } 641 642 @Override 643 public boolean lenientEquals(Institution other) { 644 if (this == other) { 645 return true; 646 } 647 return active == other.active 648 && Objects.equals(key, other.key) 649 && Objects.equals(code, other.code) 650 && Objects.equals(name, other.name) 651 && Objects.equals(description, other.description) 652 && Objects.equals(types, other.types) 653 && Objects.equals(email, other.email) 654 && Objects.equals(phone, other.phone) 655 && Objects.equals(homepage, other.homepage) 656 && Objects.equals(catalogUrls, other.catalogUrls) 657 && Objects.equals(apiUrls, other.apiUrls) 658 && Objects.equals(institutionalGovernances, other.institutionalGovernances) 659 && Objects.equals(disciplines, other.disciplines) 660 && Objects.equals(latitude, other.latitude) 661 && Objects.equals(longitude, other.longitude) 662 && LenientEqualsUtils.lenientEquals(mailingAddress, other.mailingAddress) 663 && LenientEqualsUtils.lenientEquals(address, other.address) 664 && Objects.equals(additionalNames, other.additionalNames) 665 && Objects.equals(foundingDate, other.foundingDate) 666 && Objects.equals(numberSpecimens, other.numberSpecimens) 667 && Objects.equals(logoUrl, other.logoUrl) 668 && Objects.equals(deleted, other.deleted) 669 && Objects.equals(alternativeCodes, other.alternativeCodes) 670 && Objects.equals(comments, other.comments) 671 && Objects.equals(occurrenceMappings, other.occurrenceMappings) 672 && Objects.equals(replacedBy, other.replacedBy) 673 && Objects.equals(convertedToCollection, other.convertedToCollection) 674 && Objects.equals(masterSource, other.masterSource) 675 && Objects.equals(masterSourceMetadata, other.masterSourceMetadata) 676 && Objects.equals(displayOnNHCPortal, other.displayOnNHCPortal) 677 && Objects.equals(featuredImageUrl, other.featuredImageUrl) 678 && Objects.equals(featuredImageLicense, other.featuredImageLicense) 679 && Objects.equals(featuredImageAttribution, other.featuredImageAttribution); 680 } 681}