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 org.gbif.api.util.HttpURI;
017import org.gbif.api.vocabulary.Country;
018import org.gbif.api.vocabulary.Language;
019
020import java.math.BigDecimal;
021import java.net.URI;
022import java.util.ArrayList;
023import java.util.Date;
024import java.util.List;
025import java.util.Objects;
026import java.util.StringJoiner;
027import java.util.UUID;
028
029import javax.annotation.Nullable;
030import javax.validation.constraints.Max;
031import javax.validation.constraints.Min;
032import javax.validation.constraints.NotNull;
033import javax.validation.constraints.Size;
034
035import com.fasterxml.jackson.annotation.JsonIgnore;
036
037import io.swagger.v3.oas.annotations.media.Schema;
038
039/**
040 * A GBIF data publisher.
041 */
042@Schema(
043  description = "A publishing organization is an institution endorsed by a " +
044    "GBIF Participant Node to publish datasets to GBIF."
045)
046@SuppressWarnings("unused")
047public class Organization
048    implements NetworkEntity,
049    Contactable,
050    Endpointable,
051    MachineTaggable,
052    Taggable,
053    Identifiable,
054    Commentable,
055    LenientEquals<Organization>,
056    Address {
057
058  @Schema(
059    description = "Unique GBIF key for the publishing organization.",
060    accessMode = Schema.AccessMode.READ_ONLY
061  )
062  private UUID key;
063
064  @Schema(
065    description = "The participant node which has endorsed or would endorse " +
066      "this publishing organization.\n\n" +
067      "*(NB Not required for updates.)*"
068  )
069  private UUID endorsingNodeKey;
070
071  @Schema(
072    description = "Whether the participant node in `endorsingNodeKey` has " +
073      "endorsed this publishing organization — whether `endorsementStatus == " +
074      "ENDORSED`."
075  )
076  private boolean endorsementApproved;
077
078  @Schema(
079    description = "The endorsement decision regarding this publishing " +
080      "organization made by the participant node in `endorsingNodeKey`."
081  )
082  private EndorsementStatus endorsementStatus;
083
084  @Schema(
085    description = "A shared token for this publishing organization. " +
086      "The token is used to authorize publishing or modifying datasets."
087  )
088  private String password;
089
090  @Schema(
091    description = "The title of the publishing organization.\n\n" +
092      "*(NB Not required for updates.)*"
093  )
094  private String title;
095
096  @Schema(
097    description = "The abbreviation for the publishing organization."
098  )
099  private String abbreviation;
100
101  @Schema(
102    description = "The description of the publishing organization."
103  )
104  private String description;
105
106  @Schema(
107    description = "The primary language of the description of the publishing " +
108      "organization.\n\n" +
109      "*(NB Not required for updates.)*"
110  )
111  private Language language;
112
113  @Schema(
114    description = "Email addresses associated with this publishing organization."
115  )
116  private List<String> email;
117
118  @Schema(
119    description = "Telephone numbers associated with this publishing organization."
120  )
121  private List<String> phone;
122
123  @Schema(
124    description = "Homepages with further details on the publishing organization."
125  )
126  private List<URI> homepage;
127
128  @Schema(
129    description = "A logo for the publishing organization, accessible over HTTP."
130  )
131  private URI logoUrl;
132
133  @Schema(
134    description = "Address lines other than the city, province, country and" +
135      "postal code, which have their own fields."
136  )
137  private List<String> address;
138
139  @Schema(
140    description = "The city or similar line of the publishing organization's address."
141  )
142  private String city;
143
144  @Schema(
145    description = "The province or similar line of the publishing organization's address."
146  )
147  private String province;
148
149  @Schema(
150    description = "The country or other region of the publishing organization's address."
151  )
152  private Country country;
153
154  @Schema(
155    description = "The postal code or similar line of the publishing organization's address."
156  )
157  private String postalCode;
158
159  @Schema(
160    description = "The latitude of the publishing organization."
161  )
162  private BigDecimal latitude;
163
164  @Schema(
165    description = "The longitude of the publishing organization."
166  )
167  private BigDecimal longitude;
168
169  @Schema(
170    description = "The number of datasets publishing by this publishing organization.",
171    accessMode = Schema.AccessMode.READ_ONLY
172  )
173  private int numPublishedDatasets;
174
175  @Schema(
176    description = "The GBIF username of the creator of the publishing organization.",
177    accessMode = Schema.AccessMode.READ_ONLY
178  )
179  private String createdBy;
180
181  @Schema(
182    description = "The GBIF username of the last user to modify the publishing organization.",
183    accessMode = Schema.AccessMode.READ_ONLY
184  )
185  private String modifiedBy;
186
187  @Schema(
188    description = "Timestamp of when the publishing organization was created.",
189    accessMode = Schema.AccessMode.READ_ONLY
190  )
191  private Date created;
192
193  @Schema(
194    description = "Timestamp of when the publishing organization was modified.",
195    accessMode = Schema.AccessMode.READ_ONLY
196  )
197  private Date modified;
198
199  @Schema(
200    description = "If present, the publishing organization was deleted at this time. " +
201      "It is possible for it to be restored in the future.",
202    accessMode = Schema.AccessMode.READ_ONLY
203  )
204  private Date deleted;
205
206  @Schema(
207    description = "The time when this publishing organization was endorsed by " +
208      "the linked participant node."
209  )
210  private Date endorsed;
211
212  @Schema(
213    description = "A list of contacts associated with this publishing organization.",
214    accessMode = Schema.AccessMode.READ_ONLY
215  )
216  private List<Contact> contacts = new ArrayList<>();
217
218  @Schema(
219    description = "A list of endpoints associated with this publishing organization.",
220    accessMode = Schema.AccessMode.READ_ONLY
221  )
222  private List<Endpoint> endpoints = new ArrayList<>();
223
224  @Schema(
225    description = "A list of machine tags associated with this publishing organization.",
226    accessMode = Schema.AccessMode.READ_ONLY
227  )
228  private List<MachineTag> machineTags = new ArrayList<>();
229
230  @Schema(
231    description = "A list of tags associated with this publishing organization.",
232    accessMode = Schema.AccessMode.READ_ONLY
233  )
234  private List<Tag> tags = new ArrayList<>();
235
236  @Schema(
237    description = "A list of identifiers associated with this publishing organization.",
238    accessMode = Schema.AccessMode.READ_ONLY
239  )
240  private List<Identifier> identifiers = new ArrayList<>();
241
242  @Schema(
243    description = "A list of comments associated with this publishing organization.",
244    accessMode = Schema.AccessMode.READ_ONLY
245  )
246  private List<Comment> comments = new ArrayList<>();
247
248  @Override
249  public UUID getKey() {
250    return key;
251  }
252
253  @Override
254  public void setKey(UUID key) {
255    this.key = key;
256  }
257
258  @Override
259  public String getTitle() {
260    return title;
261  }
262
263  @Override
264  public void setTitle(String title) {
265    this.title = title;
266  }
267
268  @Override
269  public String getDescription() {
270    return description;
271  }
272
273  @Override
274  public void setDescription(String description) {
275    this.description = description;
276  }
277
278  @Override
279  public Date getCreated() {
280    return created;
281  }
282
283  @Override
284  public void setCreated(Date created) {
285    this.created = created;
286  }
287
288  @Override
289  public Date getModified() {
290    return modified;
291  }
292
293  @Override
294  public void setModified(Date modified) {
295    this.modified = modified;
296  }
297
298  @Override
299  public Date getDeleted() {
300    return deleted;
301  }
302
303  @Override
304  public void setDeleted(Date deleted) {
305    this.deleted = deleted;
306  }
307
308  public Date getEndorsed() {
309    return endorsed;
310  }
311
312  public void setEndorsed(Date endorsed) {
313    this.endorsed = endorsed;
314  }
315
316  @NotNull
317  public UUID getEndorsingNodeKey() {
318    return endorsingNodeKey;
319  }
320
321  public void setEndorsingNodeKey(UUID endorsingNodeKey) {
322    this.endorsingNodeKey = endorsingNodeKey;
323  }
324
325  public boolean isEndorsementApproved() {
326    return endorsementApproved;
327  }
328
329  public void setEndorsementApproved(boolean endorsementApproved) {
330    this.endorsementApproved = endorsementApproved;
331  }
332
333  public EndorsementStatus getEndorsementStatus() {
334    return endorsementStatus;
335  }
336
337  public void setEndorsementStatus(EndorsementStatus endorsementStatus) {
338    this.endorsementStatus = endorsementStatus;
339  }
340
341  /**
342   * Get the organization password. This method is to be ignored on serialization, so that the password is not
343   * revealed in the web service response.
344   *
345   * @return organization password
346   */
347  @JsonIgnore
348  @Nullable
349  public String getPassword() {
350    return password;
351  }
352
353  public void setPassword(String password) {
354    this.password = password;
355  }
356
357  @Nullable
358  @Size(min = 1, max = 30)
359  public String getAbbreviation() {
360    return abbreviation;
361  }
362
363  public void setAbbreviation(String abbreviation) {
364    this.abbreviation = abbreviation;
365  }
366
367  @NotNull
368  public Language getLanguage() {
369    return language;
370  }
371
372  public void setLanguage(Language language) {
373    this.language = language;
374  }
375
376  @Nullable
377  @Override
378  public List<String> getEmail() {
379    return email;
380  }
381
382  @Override
383  public void setEmail(List<String> email) {
384    this.email = email;
385  }
386
387  @Nullable
388  @Override
389  public List<String> getPhone() {
390    return phone;
391  }
392
393  @Override
394  public void setPhone(List<String> phone) {
395    this.phone = phone;
396  }
397
398  @Nullable
399  @Override
400  public List<URI> getHomepage() {
401    return homepage;
402  }
403
404  @Override
405  public void setHomepage(List<URI> homepage) {
406    this.homepage = homepage;
407  }
408
409  @HttpURI
410  @Nullable
411  public URI getLogoUrl() {
412    return logoUrl;
413  }
414
415  public void setLogoUrl(URI logoUrl) {
416    this.logoUrl = logoUrl;
417  }
418
419  @Nullable
420  @Override
421  public List<String> getAddress() {
422    return address;
423  }
424
425  @Override
426  public void setAddress(List<String> address) {
427    this.address = address;
428  }
429
430  @Nullable
431  @Override
432  public String getCity() {
433    return city;
434  }
435
436  @Override
437  public void setCity(String city) {
438    this.city = city;
439  }
440
441  @Nullable
442  @Override
443  public String getProvince() {
444    return province;
445  }
446
447  @Override
448  public void setProvince(String province) {
449    this.province = province;
450  }
451
452  @NotNull
453  @Override
454  public Country getCountry() {
455    return country;
456  }
457
458  @Override
459  public void setCountry(Country country) {
460    this.country = country;
461  }
462
463  @Nullable
464  @Override
465  public String getPostalCode() {
466    return postalCode;
467  }
468
469  @Override
470  public void setPostalCode(String postalCode) {
471    this.postalCode = postalCode;
472  }
473
474  @Nullable
475  @Override
476  @JsonIgnore
477  public String getOrganization() {
478    return getTitle();
479  }
480
481  @Override
482  public void setOrganization(String organization) {
483    setTitle(organization);
484  }
485
486  @Nullable
487  @Min(-90)
488  @Max(90)
489  public BigDecimal getLatitude() {
490    return latitude;
491  }
492
493  public void setLatitude(BigDecimal latitude) {
494    this.latitude = latitude;
495  }
496
497  @Nullable
498  @Min(-180)
499  @Max(180)
500  public BigDecimal getLongitude() {
501    return longitude;
502  }
503
504  public void setLongitude(BigDecimal longitude) {
505    this.longitude = longitude;
506  }
507
508  @Min(0)
509  public int getNumPublishedDatasets() {
510    return numPublishedDatasets;
511  }
512
513  public void setNumPublishedDatasets(int numPublishedDatasets) {
514    this.numPublishedDatasets = numPublishedDatasets;
515  }
516
517  @Override
518  public String getCreatedBy() {
519    return createdBy;
520  }
521
522  @Override
523  public void setCreatedBy(String createdBy) {
524    this.createdBy = createdBy;
525  }
526
527  @Override
528  public String getModifiedBy() {
529    return modifiedBy;
530  }
531
532  @Override
533  public void setModifiedBy(String modifiedBy) {
534    this.modifiedBy = modifiedBy;
535  }
536
537  @Override
538  public List<Contact> getContacts() {
539    return contacts;
540  }
541
542  @Override
543  public void setContacts(List<Contact> contacts) {
544    this.contacts = contacts;
545  }
546
547  @Override
548  public List<Endpoint> getEndpoints() {
549    return endpoints;
550  }
551
552  @Override
553  public void setEndpoints(List<Endpoint> endpoints) {
554    this.endpoints = endpoints;
555  }
556
557  @Override
558  public void addEndpoint(Endpoint endpoint) {
559    endpoints.add(endpoint);
560  }
561
562  @Override
563  public List<MachineTag> getMachineTags() {
564    return machineTags;
565  }
566
567  @Override
568  public void setMachineTags(List<MachineTag> machineTags) {
569    this.machineTags = machineTags;
570  }
571
572  @Override
573  public void addMachineTag(MachineTag machineTag) {
574    machineTags.add(machineTag);
575  }
576
577  @Override
578  public List<Tag> getTags() {
579    return tags;
580  }
581
582  @Override
583  public void setTags(List<Tag> tags) {
584    this.tags = tags;
585  }
586
587  @Override
588  public List<Identifier> getIdentifiers() {
589    return identifiers;
590  }
591
592  @Override
593  public void setIdentifiers(List<Identifier> identifiers) {
594    this.identifiers = identifiers;
595  }
596
597  @Override
598  public List<Comment> getComments() {
599    return comments;
600  }
601
602  @Override
603  public void setComments(List<Comment> comments) {
604    this.comments = comments;
605  }
606
607  @Override
608  public boolean equals(Object o) {
609    if (this == o) {
610      return true;
611    }
612    if (o == null || getClass() != o.getClass()) {
613      return false;
614    }
615    Organization that = (Organization) o;
616    return endorsementApproved == that.endorsementApproved
617        && endorsementStatus == that.endorsementStatus
618        && numPublishedDatasets == that.numPublishedDatasets
619        && Objects.equals(key, that.key)
620        && Objects.equals(endorsingNodeKey, that.endorsingNodeKey)
621        && Objects.equals(password, that.password)
622        && Objects.equals(title, that.title)
623        && Objects.equals(abbreviation, that.abbreviation)
624        && Objects.equals(description, that.description)
625        && language == that.language
626        && Objects.equals(email, that.email)
627        && Objects.equals(phone, that.phone)
628        && Objects.equals(homepage, that.homepage)
629        && Objects.equals(logoUrl, that.logoUrl)
630        && Objects.equals(address, that.address)
631        && Objects.equals(city, that.city)
632        && Objects.equals(province, that.province)
633        && country == that.country
634        && Objects.equals(postalCode, that.postalCode)
635        && Objects.equals(latitude, that.latitude)
636        && Objects.equals(longitude, that.longitude)
637        && Objects.equals(createdBy, that.createdBy)
638        && Objects.equals(modifiedBy, that.modifiedBy)
639        && Objects.equals(created, that.created)
640        && Objects.equals(modified, that.modified)
641        && Objects.equals(deleted, that.deleted)
642        && Objects.equals(endorsed, that.endorsed)
643        && Objects.equals(contacts, that.contacts)
644        && Objects.equals(endpoints, that.endpoints)
645        && Objects.equals(machineTags, that.machineTags)
646        && Objects.equals(tags, that.tags)
647        && Objects.equals(identifiers, that.identifiers)
648        && Objects.equals(comments, that.comments);
649  }
650
651  @Override
652  public int hashCode() {
653    return Objects.hash(
654        key,
655        endorsingNodeKey,
656        endorsementApproved,
657        endorsementStatus,
658        password,
659        title,
660        abbreviation,
661        description,
662        language,
663        email,
664        phone,
665        homepage,
666        logoUrl,
667        address,
668        city,
669        province,
670        country,
671        postalCode,
672        latitude,
673        longitude,
674        numPublishedDatasets,
675        createdBy,
676        modifiedBy,
677        created,
678        modified,
679        deleted,
680        endorsed,
681        contacts,
682        endpoints,
683        machineTags,
684        tags,
685        identifiers,
686        comments);
687  }
688
689  @Override
690  public String toString() {
691    return new StringJoiner(", ", Organization.class.getSimpleName() + "[", "]")
692        .add("key=" + key)
693        .add("endorsingNodeKey=" + endorsingNodeKey)
694        .add("endorsementApproved=" + endorsementApproved)
695        .add("endorsementStatus=" + endorsementStatus)
696        .add("password='" + password + "'")
697        .add("title='" + title + "'")
698        .add("abbreviation='" + abbreviation + "'")
699        .add("description='" + description + "'")
700        .add("language=" + language)
701        .add("email=" + email)
702        .add("phone=" + phone)
703        .add("homepage=" + homepage)
704        .add("logoUrl=" + logoUrl)
705        .add("address=" + address)
706        .add("city='" + city + "'")
707        .add("province='" + province + "'")
708        .add("country=" + country)
709        .add("postalCode='" + postalCode + "'")
710        .add("latitude=" + latitude)
711        .add("longitude=" + longitude)
712        .add("numPublishedDatasets=" + numPublishedDatasets)
713        .add("createdBy='" + createdBy + "'")
714        .add("modifiedBy='" + modifiedBy + "'")
715        .add("created=" + created)
716        .add("modified=" + modified)
717        .add("deleted=" + deleted)
718        .add("endorsed=" + endorsed)
719        .add("contacts=" + contacts)
720        .add("endpoints=" + endpoints)
721        .add("machineTags=" + machineTags)
722        .add("tags=" + tags)
723        .add("identifiers=" + identifiers)
724        .add("comments=" + comments)
725        .toString();
726  }
727
728  /**
729   * A lenient equality check for business logic uniqueness. Does not include server side controlled fields such as key
730   * and createdBy, nested objects and does not include password for security reasons.
731   */
732  @Override
733  public boolean lenientEquals(Organization other) {
734    if (this == other) {
735      return true;
736    }
737    return Objects.equals(this.endorsingNodeKey, other.endorsingNodeKey)
738        && Objects.equals(this.endorsementApproved, other.endorsementApproved)
739        && Objects.equals(this.endorsementStatus, other.endorsementStatus)
740        && Objects.equals(this.title, other.title)
741        && Objects.equals(this.abbreviation, other.abbreviation)
742        && Objects.equals(this.description, other.description)
743        && Objects.equals(this.language, other.language)
744        && Objects.equals(this.email, other.email)
745        && Objects.equals(this.phone, other.phone)
746        && Objects.equals(this.homepage, other.homepage)
747        && Objects.equals(this.logoUrl, other.logoUrl)
748        && Objects.equals(this.address, other.address)
749        && Objects.equals(this.city, other.city)
750        && Objects.equals(this.province, other.province)
751        && Objects.equals(this.country, other.country)
752        && Objects.equals(this.postalCode, other.postalCode)
753        && Objects.equals(this.latitude, other.latitude)
754        && Objects.equals(this.longitude, other.longitude)
755        && Objects.equals(this.deleted, other.deleted)
756        && Objects.equals(this.endorsed, other.endorsed);
757  }
758}