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.checklistbank;
015
016import org.gbif.api.vocabulary.CitesAppendix;
017import org.gbif.api.vocabulary.Country;
018import org.gbif.api.vocabulary.DistributionStatus;
019import org.gbif.api.vocabulary.EstablishmentMeans;
020import org.gbif.api.vocabulary.LifeStage;
021import org.gbif.api.vocabulary.ThreatStatus;
022
023import java.util.Objects;
024import java.util.StringJoiner;
025
026import javax.annotation.Nullable;
027import javax.validation.constraints.Max;
028import javax.validation.constraints.Min;
029
030import io.swagger.v3.oas.annotations.media.Schema;
031
032/**
033 * Distribution Model Object represents a species distribution.
034 *
035 * @see <a href="http://rs.gbif.org/extension/gbif/1.0/distribution.xml">Distribution Definition</a>
036 */
037@SuppressWarnings("unused")
038public class Distribution implements NameUsageExtension {
039
040  private Integer taxonKey;
041  private String locationId;
042  private String locality;
043  private Country country;
044  private DistributionStatus status;
045  private LifeStage lifeStage;
046  private String temporal;
047  private ThreatStatus threatStatus;
048  private EstablishmentMeans establishmentMeans;
049  private CitesAppendix appendixCites;
050  private String source;
051  private Integer sourceTaxonKey;
052  private Integer startDayOfYear;
053  private Integer endDayOfYear;
054  private String remarks;
055
056  /**
057   * The name usage "taxon" key this description belongs to.
058   */
059  @Schema(description = "The name usage “taxon“ key to which this species profile belongs.")
060  @Override
061  public Integer getTaxonKey() {
062    return taxonKey;
063  }
064
065  @Override
066  public void setTaxonKey(Integer taxonKey) {
067    this.taxonKey = taxonKey;
068  }
069
070  /**
071   * The CITES (Convention on International Trade in Endangered Species of Wild Fauna and Flora) Appendix number under which the
072   * taxon is listed. It is possible to have different appendix numbers for different areas, but "global" as an area is
073   * also valid if it's the same worldwide see also http://www.cites.org/eng/app/index.shtml
074   * <blockquote>
075   * <p>
076   * <i>Example:</i> II
077   * </p>
078   * </blockquote>
079   *
080   * @return the appendixCites.
081   */
082  @Schema(description = "The CITES (Convention on International Trade in Endangered Species of Wild Fauna and Flora) " +
083    "Appendix number under which the taxon is listed.\n\n" +
084    "It is possible to have different appendix numbers for different areas, but “global” as an area is also valid.")
085  @Nullable
086  public CitesAppendix getAppendixCites() {
087    return appendixCites;
088  }
089
090  /**
091   * @param appendixCites the appendixCites to set
092   */
093  public void setAppendixCites(CitesAppendix appendixCites) {
094    this.appendixCites = appendixCites;
095  }
096
097  /**
098   * @return the country
099   */
100  @Schema(description = "The country")
101  @Nullable
102  public Country getCountry() {
103    return country;
104  }
105
106  /**
107   * @param country the country to set
108   */
109  public void setCountry(Country country) {
110    this.country = country;
111  }
112
113  /**
114   * Seasonal temporal subcontext within the eventDate context. The latest ordinal day of the year on which the
115   * distribution record is valid.
116   * <blockquote>
117   * <p>
118   * <i>Example:</i> 120
119   * </p>
120   * </blockquote>
121   *
122   * @return the endDayOfYear.
123   */
124  @Schema(description = "Seasonal temporal subcontext within the eventDate context. " +
125    "The latest ordinal day of the year on which the distribution record is valid.")
126  @Nullable
127  @Min(1)
128  @Max(366)
129  public Integer getEndDayOfYear() {
130    return endDayOfYear;
131  }
132
133  /**
134   * @param endDayOfYear the endDayOfYear to set
135   */
136  public void setEndDayOfYear(Integer endDayOfYear) {
137    this.endDayOfYear = endDayOfYear;
138  }
139
140  /**
141   * Term describing whether the organism occurs natively, is introduced or cultivated.
142   * <blockquote>
143   * <p>
144   * <i>Example:</i> introduced
145   * </p>
146   * </blockquote>
147   *
148   * @return the establishmentMeans
149   */
150  @Schema(description = "Term describing whether the organism occurs natively, is introduced or cultivated.")
151  @Nullable
152  public EstablishmentMeans getEstablishmentMeans() {
153    return establishmentMeans;
154  }
155
156  /**
157   * @param establishmentMeans the establishmentMeans to set
158   */
159  public void setEstablishmentMeans(EstablishmentMeans establishmentMeans) {
160    this.establishmentMeans = establishmentMeans;
161  }
162
163  /**
164   * The distribution information pertains solely to a specific life stage of the taxon.
165   * <blockquote>
166   * <p>
167   * <i>Example:</i> adult
168   * </p>
169   * </blockquote>
170   *
171   * @return the lifeStage
172   *
173   * @see <a href="http://rs.gbif.org/vocabulary/gbif/life_stage.xml">life stage vocabulary for recommended values</a>
174   */
175  @Schema(description = "The distribution information pertains solely to a specific life stage of the taxon.")
176  @Nullable
177  public LifeStage getLifeStage() {
178    return lifeStage;
179  }
180
181  /**
182   * @param lifeStage the lifeStage to set
183   */
184  public void setLifeStage(LifeStage lifeStage) {
185    this.lifeStage = lifeStage;
186  }
187
188  /**
189   * The verbatim name of the area this distribution record is about.
190   * <blockquote>
191   * <p>
192   * <i>Example:</i> Patagonia
193   * </p>
194   * </blockquote>
195   *
196   * @return the locality
197   */
198  @Schema(description = "The verbatim name of the area this distribution record is about.")
199  @Nullable
200  public String getLocality() {
201    return locality;
202  }
203
204  /**
205   * @param locality the locality to set
206   */
207  public void setLocality(String locality) {
208    this.locality = locality;
209  }
210
211  /**
212   * A code for the named area this distributon record is about.
213   * See http://en.wikipedia.org/wiki/ISO_3166-2 for state codes within a country,
214   * otherwise use a prefix for each code to indicate the source of the code.
215   * <p/>
216   * <blockqoute>
217   * <p>
218   * <i>Example:</i> TDWG:AGS-TF <i>Example:</i> ISO3166:AR <i>Example:</i> WOEID:564721
219   * </p>
220   * </blockquote>
221   *
222   * @return the location id
223   */
224  @Schema(description = " A code for the named area this distributon record is about.")
225  public String getLocationId() {
226    return locationId;
227  }
228
229  /**
230   * @param locationId the locationId to set
231   */
232  public void setLocationId(String locationId) {
233    this.locationId = locationId;
234  }
235
236  /**
237   * Additional notes on the distribution.
238   *
239   * @return the notes
240   */
241  @Schema(description = "Additional notes on the distribution.")
242  @Nullable
243  public String getRemarks() {
244    return remarks;
245  }
246
247  public void setRemarks(String remarks) {
248    this.remarks = remarks;
249  }
250
251  /**
252   * Source reference for this distribution record. Can be proper publication citation, a webpage URL, etc.
253   * <blockquote>
254   * <p>
255   * <i>Example:</i> "Euro+Med Plantbase - the information resource for Euro-Mediterranean plant diversity (2006-).
256   * Published on the Internet http://ww2.bgbm.org/EuroPlusMed/ July, 2009"
257   * </p>
258   * </blockquote>
259   *
260   * @return the source
261   */
262  @Schema(description = "Bibliographic citation referencing a source for the distribution.")
263  @Nullable
264  @Override
265  public String getSource() {
266    return source;
267  }
268
269  /**
270   * @param source the source to set
271   */
272  @Override
273  public void setSource(String source) {
274    this.source = source;
275  }
276
277  @Schema(description = "The name usage key of the taxon in the checklist including this distribution.")
278  @Nullable
279  @Override
280  public Integer getSourceTaxonKey() {
281    return sourceTaxonKey;
282  }
283
284  @Override
285  public void setSourceTaxonKey(Integer sourceTaxonKey) {
286    this.sourceTaxonKey = sourceTaxonKey;
287  }
288
289  /**
290   * Seasonal temporal subcontext within the eventDate context. Useful for migratory species. The earliest ordinal day
291   * of the year on which the distribution record is valid. Numbering starts with 1 for 1 January and ends with 365 or 366
292   * for 31 December.
293   * <blockquote>
294   * <p>
295   * <i>Example:</i> 90
296   * </p>
297   * </blockquote>
298   *
299   * @return the startDayOfYear.
300   */
301  @Schema(description = "Seasonal temporal subcontext within the eventDate context. Useful for migratory species.\n\n" +
302    "The earliest ordinal day of the year on which the distribution record is valid. Numbering starts with 1 for " +
303    "1 January and ends with 365 or 366 for 31 December.")
304  @Nullable
305  @Min(1)
306  @Max(366)
307  public Integer getStartDayOfYear() {
308    return startDayOfYear;
309  }
310
311  /**
312   * @param startDayOfYear the startDayOfYear to set
313   */
314  public void setStartDayOfYear(Integer startDayOfYear) {
315    this.startDayOfYear = startDayOfYear;
316  }
317
318  /**
319   * Term describing the occurrence status of the organism in the given area based on how frequent the species occurs.
320   * <blockquote>
321   * <p>
322   * <i>Example:</i> absent
323   * </p>
324   * </blockquote>
325   *
326   * @return the status.
327   *
328   * @see <a href="http://rs.gbif.org/vocabulary/gbif/distribution_status_2020-05-14.xml">occurrence status vocabulary</a> for recommended values
329   */
330  @Schema(description = "Term describing the occurrence status of the organism in the given area based on how frequent the species occurs.")
331  @Nullable
332  public DistributionStatus getStatus() {
333    return status;
334  }
335
336  /**
337   * @param status the status to set
338   */
339  public void setStatus(DistributionStatus status) {
340    this.status = status;
341  }
342
343  /**
344   * Relevant temporal context for this entire distribution record including all properties preferably given as a year
345   * range or single year on which the distribution record is valid. For the same area and taxon there could therefore
346   * be several records with different temporal context, e.g. in 5-year intervals for invasive species.
347   * <blockquote>
348   *   <p><i>Example:</i> "1930"; "1939-1945"</p>
349   * </blockquote>
350   * @return the temporal
351   */
352  @Schema(description = "Relevant temporal context for this entire distribution record including all properties, " +
353    "preferably given as a year range or single year on which the distribution record is valid.\n\n" +
354    "For the same area and taxon there could therefore be several records with different temporal context, " +
355    "e.g. in 5-year intervals for invasive species.")
356  @Nullable
357  public String getTemporal() {
358    return temporal;
359  }
360
361  /**
362   * @param temporal the temporal to set
363   */
364  public void setTemporal(String temporal) {
365    this.temporal = temporal;
366  }
367
368  /**
369   * Threat status of a species as defined by IUCN
370   * (http://www.iucnredlist.org/static/categories_criteria_3_1#categories).
371   * <blockquote>
372   * <p>
373   * <i>Examples:</i> "EX" - "EW" - "CR"
374   * </p>
375   * </blockquote>
376   *
377   * @return the threatStatus.
378   *
379   * @see <a href="http://rs.gbif.org/vocabulary/iucn/threat_status.xml">threat status vocabulary for recommended
380   *      values</a>
381   */
382  @Schema(description = "Threat status of a species as defined by IUCN.")
383  @Nullable
384  public ThreatStatus getThreatStatus() {
385    return threatStatus;
386  }
387
388  /**
389   * @param threatStatus the threatStatus to set
390   */
391  public void setThreatStatus(ThreatStatus threatStatus) {
392    this.threatStatus = threatStatus;
393  }
394
395  @Override
396  public boolean equals(Object o) {
397    if (this == o) {
398      return true;
399    }
400    if (o == null || getClass() != o.getClass()) {
401      return false;
402    }
403    Distribution that = (Distribution) o;
404    return Objects.equals(taxonKey, that.taxonKey) &&
405      Objects.equals(locationId, that.locationId) &&
406      Objects.equals(locality, that.locality) &&
407      country == that.country &&
408      status == that.status &&
409      lifeStage == that.lifeStage &&
410      Objects.equals(temporal, that.temporal) &&
411      threatStatus == that.threatStatus &&
412      establishmentMeans == that.establishmentMeans &&
413      appendixCites == that.appendixCites &&
414      Objects.equals(source, that.source) &&
415      Objects.equals(sourceTaxonKey, that.sourceTaxonKey) &&
416      Objects.equals(startDayOfYear, that.startDayOfYear) &&
417      Objects.equals(endDayOfYear, that.endDayOfYear);
418  }
419
420  @Override
421  public int hashCode() {
422    return Objects
423      .hash(taxonKey, locationId, locality, country, status, lifeStage, temporal, threatStatus,
424        establishmentMeans, appendixCites, source, sourceTaxonKey, startDayOfYear, endDayOfYear);
425  }
426
427  @Override
428  public String toString() {
429    return new StringJoiner(", ", Distribution.class.getSimpleName() + "[", "]")
430      .add("taxonKey=" + taxonKey)
431      .add("locationId='" + locationId + "'")
432      .add("locality='" + locality + "'")
433      .add("country=" + country)
434      .add("status=" + status)
435      .add("lifeStage=" + lifeStage)
436      .add("temporal='" + temporal + "'")
437      .add("threatStatus=" + threatStatus)
438      .add("establishmentMeans=" + establishmentMeans)
439      .add("appendixCites=" + appendixCites)
440      .add("source='" + source + "'")
441      .add("sourceTaxonKey=" + sourceTaxonKey)
442      .add("startDayOfYear=" + startDayOfYear)
443      .add("endDayOfYear=" + endDayOfYear)
444      .add("remarks='" + remarks + "'")
445      .toString();
446  }
447}