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