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}