001/* 002 * Copyright 2020 Global Biodiversity Information Facility (GBIF) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.gbif.api.model.registry; 017 018import org.gbif.api.util.HttpURI; 019import org.gbif.api.vocabulary.Continent; 020import org.gbif.api.vocabulary.Country; 021import org.gbif.api.vocabulary.GbifRegion; 022import org.gbif.api.vocabulary.NodeType; 023import org.gbif.api.vocabulary.ParticipationStatus; 024 025import java.net.URI; 026import java.util.ArrayList; 027import java.util.Date; 028import java.util.List; 029import java.util.Objects; 030import java.util.StringJoiner; 031import java.util.UUID; 032 033import javax.annotation.Nullable; 034import javax.validation.constraints.NotNull; 035import javax.validation.constraints.Size; 036 037import io.swagger.v3.oas.annotations.ExternalDocumentation; 038import io.swagger.v3.oas.annotations.Hidden; 039import io.swagger.v3.oas.annotations.media.Schema; 040 041/** 042 * A GBIF participant node. 043 * 044 * Primarily managed in the GBIF Directory. 045 */ 046@Schema( 047 description = "A participant node, a country and its nominated organization " + 048 "or an international organization which is a member of GBIF.\n\n" + 049 "Note that participant nodes are managed in an internal GBIF system," + 050 "so methods to create, update and delete participant nodes are generally " + 051 "used only to synchronize the two systems.", 052 externalDocs = @ExternalDocumentation( 053 description = "Further information on GBIF's governance structure", 054 url = "https://www.gbif.org/what-is-gbif" 055 ) 056) 057@SuppressWarnings("unused") 058public class Node 059 implements NetworkEntity, 060 Contactable, 061 Taggable, 062 MachineTaggable, 063 Commentable, 064 Identifiable, 065 Endpointable, 066 LenientEquals<Node>, 067 Address { 068 069 @Schema( 070 description = "Unique GBIF key for the participant node.", 071 accessMode = Schema.AccessMode.READ_ONLY 072 ) 073 private UUID key; 074 075 @Schema( 076 description = "The membership type of the participant node.", 077 accessMode = Schema.AccessMode.READ_ONLY 078 ) 079 private NodeType type; 080 081 @Schema( 082 description = "The membership status of the participant node.", 083 accessMode = Schema.AccessMode.READ_ONLY 084 ) 085 private ParticipationStatus participationStatus; 086 087 @Schema( 088 description = "The year the participant node first joined GBIF.", 089 minimum = "2001", 090 accessMode = Schema.AccessMode.READ_ONLY 091 ) 092 private Integer participantSince; 093 094 @Schema( 095 description = "The date the participant node signed the GBIF Memorandum " + 096 "of Understanding.", 097 minimum = "2001-01-18", 098 accessMode = Schema.AccessMode.READ_ONLY 099 ) 100 private Date dateSignedMOU; 101 102 @Schema( 103 description = "The political region, based on " + 104 "[IPBES regions](https://www.nature.com/articles/sdata20167/figures/1), " + 105 "to which this participant node belongs.", 106 accessMode = Schema.AccessMode.READ_ONLY 107 ) 108 private GbifRegion gbifRegion; 109 110 @Schema( 111 description = "Not used" 112 ) 113 @Hidden 114 private Continent continent; 115 116 @Schema( 117 description = "The name of the participant node.", 118 example = "U.S. Geological Survey", 119 accessMode = Schema.AccessMode.READ_ONLY 120 ) 121 private String title; 122 123 @Schema( 124 description = "The name of the participant.", 125 example = "United States of America", 126 accessMode = Schema.AccessMode.READ_ONLY 127 ) 128 private String participantTitle; 129 130 @Schema( 131 description = "The abbreviation for the participant node.", 132 example = "USGS", 133 accessMode = Schema.AccessMode.READ_ONLY 134 ) 135 private String abbreviation; 136 137 @Schema( 138 description = "The description of the participant node.", 139 accessMode = Schema.AccessMode.READ_ONLY 140 ) 141 private String description; 142 143 @Schema( 144 description = "Email addresses associated with this participant node.", 145 accessMode = Schema.AccessMode.READ_ONLY 146 ) 147 private List<String> email = new ArrayList<>(); 148 149 @Schema( 150 description = "Telephone numbers associated with this participant node.", 151 accessMode = Schema.AccessMode.READ_ONLY 152 ) 153 private List<String> phone = new ArrayList<>(); 154 155 @Schema( 156 description = "Homepages with further details on the participant node.", 157 accessMode = Schema.AccessMode.READ_ONLY 158 ) 159 private List<URI> homepage = new ArrayList<>(); 160 161 @Schema( 162 description = "A logo for the participant node, accessible over HTTP.", 163 accessMode = Schema.AccessMode.READ_ONLY 164 ) 165 private URI logoUrl; 166 167 @Schema( 168 description = "Not used" 169 ) 170 @Hidden 171 private String organization; 172 173 @Schema( 174 description = "Address lines other than the city, province, country and" + 175 "postal code, which have their own fields." 176 ) 177 private List<String> address = new ArrayList<>(); 178 179 @Schema( 180 description = "The city or similar line of the participant node's address." 181 ) 182 private String city; 183 184 @Schema( 185 description = "The province or similar line of the participant node's address." 186 ) 187 private String province; 188 189 @Schema( 190 description = "The country or other region of the participant node's address." 191 ) 192 private Country country; 193 194 @Schema( 195 description = "The postal code or similar line of the participant node's address." 196 ) 197 private String postalCode; 198 199 @Schema( 200 description = "The GBIF username of the creator of the participant node.", 201 accessMode = Schema.AccessMode.READ_ONLY 202 ) 203 private String createdBy; 204 205 @Schema( 206 description = "The GBIF username of the last user to modify the participant node.", 207 accessMode = Schema.AccessMode.READ_ONLY 208 ) 209 private String modifiedBy; 210 211 @Schema( 212 description = "Timestamp of when the participant node was created *in " + 213 "the Registry*. See also, `participantSince`.", 214 accessMode = Schema.AccessMode.READ_ONLY 215 ) 216 private Date created; 217 218 @Schema( 219 description = "Timestamp of when the participant node was modified.", 220 accessMode = Schema.AccessMode.READ_ONLY 221 ) 222 private Date modified; 223 224 @Schema( 225 description = "If present, the participant node was deleted at this time. " + 226 "It is possible for it to be restored in the future.", 227 accessMode = Schema.AccessMode.READ_ONLY 228 ) 229 private Date deleted; 230 231 @Schema( 232 description = "A list of contacts associated with this participant node.", 233 accessMode = Schema.AccessMode.READ_ONLY 234 ) 235 private List<Contact> contacts = new ArrayList<>(); 236 237 @Schema( 238 description = "A list of endpoints associated with this participant node.", 239 accessMode = Schema.AccessMode.READ_ONLY 240 ) 241 private List<Endpoint> endpoints = new ArrayList<>(); 242 243 @Schema( 244 description = "A list of machine tags associated with this participant node.", 245 accessMode = Schema.AccessMode.READ_ONLY 246 ) 247 private List<MachineTag> machineTags = new ArrayList<>(); 248 249 @Schema( 250 description = "A list of tags associated with this participant node.", 251 accessMode = Schema.AccessMode.READ_ONLY 252 ) 253 private List<Tag> tags = new ArrayList<>(); 254 255 @Schema( 256 description = "A list of identifiers associated with this participant node.", 257 accessMode = Schema.AccessMode.READ_ONLY 258 ) 259 private List<Identifier> identifiers = new ArrayList<>(); 260 261 @Schema( 262 description = "A list of comments associated with this participant node.", 263 accessMode = Schema.AccessMode.READ_ONLY 264 ) 265 private List<Comment> comments = new ArrayList<>(); 266 267 @Override 268 public UUID getKey() { 269 return key; 270 } 271 272 @Override 273 public void setKey(UUID key) { 274 this.key = key; 275 } 276 277 @Override 278 public String getTitle() { 279 return title; 280 } 281 282 @Override 283 public void setTitle(String title) { 284 this.title = title; 285 } 286 287 public String getParticipantTitle() { 288 return participantTitle; 289 } 290 291 public void setParticipantTitle(String participantTitle) { 292 this.participantTitle = participantTitle; 293 } 294 295 @Nullable 296 @Size(min = 1, max = 10) 297 public String getAbbreviation() { 298 return abbreviation; 299 } 300 301 public void setAbbreviation(String abbreviation) { 302 this.abbreviation = abbreviation; 303 } 304 305 @Override 306 public String getDescription() { 307 return description; 308 } 309 310 @Override 311 public void setDescription(String description) { 312 this.description = description; 313 } 314 315 @Override 316 public Date getCreated() { 317 return created; 318 } 319 320 @Override 321 public void setCreated(Date created) { 322 this.created = created; 323 } 324 325 @Override 326 public Date getModified() { 327 return modified; 328 } 329 330 @Override 331 public void setModified(Date modified) { 332 this.modified = modified; 333 } 334 335 @Override 336 public Date getDeleted() { 337 return deleted; 338 } 339 340 @Override 341 public void setDeleted(Date deleted) { 342 this.deleted = deleted; 343 } 344 345 @NotNull 346 public NodeType getType() { 347 return type; 348 } 349 350 public void setType(NodeType type) { 351 this.type = type; 352 } 353 354 @NotNull 355 public ParticipationStatus getParticipationStatus() { 356 return participationStatus; 357 } 358 359 public void setParticipationStatus(ParticipationStatus participationStatus) { 360 this.participationStatus = participationStatus; 361 } 362 363 /** 364 * 4 digit year since the node participant first joined GBIF. 365 */ 366 @Nullable 367 public Integer getParticipantSince() { 368 return participantSince; 369 } 370 371 public void setParticipantSince(Integer participantSince) { 372 this.participantSince = participantSince; 373 } 374 375 public Date getDateSignedMOU() { 376 return dateSignedMOU; 377 } 378 379 public void setDateSignedMOU(Date dateSignedMOU) { 380 this.dateSignedMOU = dateSignedMOU; 381 } 382 383 @Nullable 384 public GbifRegion getGbifRegion() { 385 return gbifRegion; 386 } 387 388 public void setGbifRegion(GbifRegion gbifRegion) { 389 this.gbifRegion = gbifRegion; 390 } 391 392 @Nullable 393 public Continent getContinent() { 394 return continent; 395 } 396 397 public void setContinent(Continent continent) { 398 this.continent = continent; 399 } 400 401 @Nullable 402 @Override 403 public List<String> getEmail() { 404 return email; 405 } 406 407 @Override 408 public void setEmail(List<String> email) { 409 this.email = email; 410 } 411 412 @Nullable 413 @Override 414 public List<String> getPhone() { 415 return phone; 416 } 417 418 @Override 419 public void setPhone(List<String> phone) { 420 this.phone = phone; 421 } 422 423 @Nullable 424 @Override 425 public List<URI> getHomepage() { 426 return homepage; 427 } 428 429 @Override 430 public void setHomepage(List<URI> homepage) { 431 this.homepage = homepage; 432 } 433 434 @HttpURI 435 @Nullable 436 public URI getLogoUrl() { 437 return logoUrl; 438 } 439 440 public void setLogoUrl(URI logoUrl) { 441 this.logoUrl = logoUrl; 442 } 443 444 @Nullable 445 @Override 446 public String getOrganization() { 447 return organization; 448 } 449 450 @Override 451 public void setOrganization(String organization) { 452 this.organization = organization; 453 } 454 455 @Nullable 456 @Override 457 public List<String> getAddress() { 458 return address; 459 } 460 461 @Override 462 public void setAddress(List<String> address) { 463 this.address = address; 464 } 465 466 @Nullable 467 @Size(min = 1) 468 @Override 469 public String getCity() { 470 return city; 471 } 472 473 @Override 474 public void setCity(String city) { 475 this.city = city; 476 } 477 478 @Nullable 479 @Size(min = 1) 480 @Override 481 public String getProvince() { 482 return province; 483 } 484 485 @Override 486 public void setProvince(String province) { 487 this.province = province; 488 } 489 490 @Nullable 491 @Override 492 public Country getCountry() { 493 return country; 494 } 495 496 @Override 497 public void setCountry(Country country) { 498 this.country = country; 499 } 500 501 @Nullable 502 @Size(min = 1) 503 @Override 504 public String getPostalCode() { 505 return postalCode; 506 } 507 508 @Override 509 public void setPostalCode(String postalCode) { 510 this.postalCode = postalCode; 511 } 512 513 @Override 514 public String getCreatedBy() { 515 return createdBy; 516 } 517 518 @Override 519 public void setCreatedBy(String createdBy) { 520 this.createdBy = createdBy; 521 } 522 523 @Override 524 public String getModifiedBy() { 525 return modifiedBy; 526 } 527 528 @Override 529 public void setModifiedBy(String modifiedBy) { 530 this.modifiedBy = modifiedBy; 531 } 532 533 @Override 534 public List<Contact> getContacts() { 535 return contacts; 536 } 537 538 @Override 539 public void setContacts(List<Contact> contacts) { 540 this.contacts = contacts; 541 } 542 543 @Override 544 public List<Endpoint> getEndpoints() { 545 return endpoints; 546 } 547 548 @Override 549 public void setEndpoints(List<Endpoint> endpoints) { 550 this.endpoints = endpoints; 551 } 552 553 @Override 554 public void addEndpoint(Endpoint endpoint) { 555 endpoints.add(endpoint); 556 } 557 558 @Override 559 public List<MachineTag> getMachineTags() { 560 return machineTags; 561 } 562 563 @Override 564 public void setMachineTags(List<MachineTag> machineTags) { 565 this.machineTags = machineTags; 566 } 567 568 @Override 569 public void addMachineTag(MachineTag machineTag) { 570 machineTags.add(machineTag); 571 } 572 573 @Override 574 public List<Tag> getTags() { 575 return tags; 576 } 577 578 @Override 579 public void setTags(List<Tag> tags) { 580 this.tags = tags; 581 } 582 583 @Override 584 public List<Identifier> getIdentifiers() { 585 return identifiers; 586 } 587 588 @Override 589 public void setIdentifiers(List<Identifier> identifiers) { 590 this.identifiers = identifiers; 591 } 592 593 @Override 594 public List<Comment> getComments() { 595 return comments; 596 } 597 598 @Override 599 public void setComments(List<Comment> comments) { 600 this.comments = comments; 601 } 602 603 @Override 604 public boolean equals(Object o) { 605 if (this == o) { 606 return true; 607 } 608 if (o == null || getClass() != o.getClass()) { 609 return false; 610 } 611 Node node = (Node) o; 612 return Objects.equals(key, node.key) 613 && type == node.type 614 && participationStatus == node.participationStatus 615 && Objects.equals(participantSince, node.participantSince) 616 && Objects.equals(dateSignedMOU, node.dateSignedMOU) 617 && gbifRegion == node.gbifRegion 618 && continent == node.continent 619 && Objects.equals(title, node.title) 620 && Objects.equals(participantTitle, node.participantTitle) 621 && Objects.equals(abbreviation, node.abbreviation) 622 && Objects.equals(description, node.description) 623 && Objects.equals(email, node.email) 624 && Objects.equals(phone, node.phone) 625 && Objects.equals(homepage, node.homepage) 626 && Objects.equals(logoUrl, node.logoUrl) 627 && Objects.equals(organization, node.organization) 628 && Objects.equals(address, node.address) 629 && Objects.equals(city, node.city) 630 && Objects.equals(province, node.province) 631 && country == node.country 632 && Objects.equals(postalCode, node.postalCode) 633 && Objects.equals(createdBy, node.createdBy) 634 && Objects.equals(modifiedBy, node.modifiedBy) 635 && Objects.equals(created, node.created) 636 && Objects.equals(modified, node.modified) 637 && Objects.equals(deleted, node.deleted) 638 && Objects.equals(contacts, node.contacts) 639 && Objects.equals(endpoints, node.endpoints) 640 && Objects.equals(machineTags, node.machineTags) 641 && Objects.equals(tags, node.tags) 642 && Objects.equals(identifiers, node.identifiers) 643 && Objects.equals(comments, node.comments); 644 } 645 646 @Override 647 public int hashCode() { 648 return Objects.hash( 649 key, 650 type, 651 participationStatus, 652 participantSince, 653 dateSignedMOU, 654 gbifRegion, 655 continent, 656 title, 657 participantTitle, 658 abbreviation, 659 description, 660 email, 661 phone, 662 homepage, 663 logoUrl, 664 organization, 665 address, 666 city, 667 province, 668 country, 669 postalCode, 670 createdBy, 671 modifiedBy, 672 created, 673 modified, 674 deleted, 675 contacts, 676 endpoints, 677 machineTags, 678 tags, 679 identifiers, 680 comments); 681 } 682 683 @Override 684 public String toString() { 685 return new StringJoiner(", ", Node.class.getSimpleName() + "[", "]") 686 .add("key=" + key) 687 .add("type=" + type) 688 .add("participationStatus=" + participationStatus) 689 .add("participantSince=" + participantSince) 690 .add("dateSignedMOU=" + dateSignedMOU) 691 .add("gbifRegion=" + gbifRegion) 692 .add("continent=" + continent) 693 .add("title='" + title + "'") 694 .add("participantTitle='" + participantTitle + "'") 695 .add("abbreviation='" + abbreviation + "'") 696 .add("description='" + description + "'") 697 .add("email=" + email) 698 .add("phone=" + phone) 699 .add("homepage=" + homepage) 700 .add("logoUrl=" + logoUrl) 701 .add("organization='" + organization + "'") 702 .add("address=" + address) 703 .add("city='" + city + "'") 704 .add("province='" + province + "'") 705 .add("country=" + country) 706 .add("postalCode='" + postalCode + "'") 707 .add("createdBy='" + createdBy + "'") 708 .add("modifiedBy='" + modifiedBy + "'") 709 .add("created=" + created) 710 .add("modified=" + modified) 711 .add("deleted=" + deleted) 712 .add("contacts=" + contacts) 713 .add("endpoints=" + endpoints) 714 .add("machineTags=" + machineTags) 715 .add("tags=" + tags) 716 .add("identifiers=" + identifiers) 717 .add("comments=" + comments) 718 .toString(); 719 } 720 721 /** 722 * Compares the entities for business logic equality using a very lenient approach. 723 * Only fields persisted in the registry database are used in the comparison, excluding any nested properties and 724 * supplementary information which can be added from external databases such as the IMS. Server controlled values such 725 * as key and createdBy are omitted. 726 */ 727 @Override 728 public boolean lenientEquals(Node other) { 729 if (this == other) { 730 return true; 731 } 732 return Objects.equals(this.type, other.type) 733 && Objects.equals(this.participationStatus, other.participationStatus) 734 && Objects.equals(this.gbifRegion, other.gbifRegion) 735 && Objects.equals(this.continent, other.continent) 736 && Objects.equals(this.title, other.title) 737 && Objects.equals(this.participantTitle, other.participantTitle) 738 && Objects.equals(this.country, other.country); 739 } 740}