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.occurrence.search;
015import com.fasterxml.jackson.annotation.*;
016
017import com.fasterxml.jackson.core.JacksonException;
018
019import com.fasterxml.jackson.databind.DeserializationContext;
020import com.fasterxml.jackson.databind.JsonDeserializer;
021
022import com.fasterxml.jackson.databind.KeyDeserializer;
023import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
024import com.fasterxml.jackson.databind.node.ObjectNode;
025
026import org.gbif.api.annotation.Experimental;
027import org.gbif.api.model.common.search.SearchParameter;
028import org.gbif.api.util.IsoDateInterval;
029import org.gbif.api.vocabulary.BasisOfRecord;
030import org.gbif.api.vocabulary.Continent;
031import org.gbif.api.vocabulary.Country;
032import org.gbif.api.vocabulary.EndpointType;
033import org.gbif.api.vocabulary.GbifRegion;
034import org.gbif.api.vocabulary.License;
035import org.gbif.api.vocabulary.MediaType;
036import org.gbif.api.vocabulary.OccurrenceIssue;
037import org.gbif.api.vocabulary.OccurrenceStatus;
038import org.gbif.api.vocabulary.TaxonomicStatus;
039
040import java.io.IOException;
041import java.io.Serializable;
042import java.lang.reflect.Field;
043import java.util.ArrayList;
044import java.util.Date;
045import java.util.List;
046import java.util.Objects;
047import java.util.Optional;
048import java.util.UUID;
049
050/**
051 * Supported query parameters by the occurrence search and download service.
052 * For download predicates only the numerical types support comparisons other than equals.
053 */
054@JsonDeserialize(as = OccurrenceSearchParameter.class, using = OccurrenceSearchParameter.OccurrenceSearchParameterDeserializer.class)
055public class OccurrenceSearchParameter implements SearchParameter, Serializable {
056
057  /**
058   * The dataset key as a UUID.
059   */
060  public final static OccurrenceSearchParameter DATASET_KEY = new OccurrenceSearchParameter("DATASET_KEY", UUID.class);
061
062  /**
063   * The checklist key to use for taxonomy matching.
064   */
065  public final static OccurrenceSearchParameter CHECKLIST_KEY = new OccurrenceSearchParameter("CHECKLIST_KEY", String.class);
066
067  /**
068   * The 4 digit year. A year of 98 will be 98 common era, not 1998.
069   * This parameter accepts comma separated range values, e.g.:
070   * <dl>
071   * <dt>*,1810</dt>
072   * <dd>Found before or equal to 1810</dd>
073   * <dt>1848,1933</dt>
074   * <dd>Year between 1848 and 1933</dd>
075   * </dl>
076   */
077  public final static OccurrenceSearchParameter YEAR = new OccurrenceSearchParameter("YEAR", Integer.class);
078
079  /**
080   * The month of the year, starting with 1 for January.
081   * A month query can be used to retrieve seasonal records when used without a year or a year range.
082   * This parameter accepts comma separated range values, e.g.:
083   * <dl>
084   * <dt>4,8</dt>
085   * <dd>Month between April and August</dd>
086   * </dl>
087   */
088  public final static OccurrenceSearchParameter MONTH = new OccurrenceSearchParameter("MONTH", Integer.class);
089
090  /**
091   * The day of the month.
092   * This parameter accepts comma separated range values, e.g.:
093   * <dl>
094   * <dt>24,28</dt>
095   * <dd>Day of the month between 24 and 28</dd>
096   * </dl>
097   */
098  public final static OccurrenceSearchParameter DAY = new OccurrenceSearchParameter("DAY", Integer.class);
099
100  /**
101   * The earliest integer day of the year on which the event occurred (1 for January 1, 365 for December 31, except in a
102   * leap year, in which case it is 366).
103   */
104  public final static OccurrenceSearchParameter START_DAY_OF_YEAR = new OccurrenceSearchParameter("START_DAY_OF_YEAR", Integer.class);
105
106  /**
107   * The latest integer day of the year on which the event occurred (1 for January 1, 365 for December 31, except in a
108   * leap year, in which case it is 366).
109   */
110  public final static OccurrenceSearchParameter END_DAY_OF_YEAR = new OccurrenceSearchParameter("END_DAY_OF_YEAR", Integer.class);
111
112  /**
113   * Event date (date the occurrence was recorded) in ISO 8601 formats:yyyy, yyyy-MM, yyyy-MM-dd and MM-dd.
114   * This parameter accepts comma separated range values, examples of valid ranges are:
115   * <dl>
116   * <dt>2001-02-11,2010-01-10</dt>
117   * <dd>Dates between 2001-02-11 and 2010-01-10</dd>
118   * <dt>2001-02,2010-01</dt>
119   * <dd>Dates between first day of 2001-02 and last day of 2010-01</dd>
120   * <dt>2001,2010</dt>
121   * <dd>Dates between first day of 2001 and last day of 2010</dd>
122   * <dt>2001,2010-01</dt>
123   * <dd>Dates between first day of 2001 and last day of 2010-01</dd>
124   * <dt>2001-01-10,2010</dt>
125   * <dd>Dates between 2001-01-10 and last day of 2010</dd>
126   * <dt>2001-01-10,*</dt>
127   * <dd>Dates after 2001-01-10</dd>
128   * <dt>*,2001-01-10</dt>
129   * <dd>Dates before 2001-01-10</dd>
130   * <dt>*</dt>
131   * <dd>all dates</dd>
132   * </dl>
133   */
134  public final static OccurrenceSearchParameter EVENT_DATE = new OccurrenceSearchParameter("EVENT_DATE", IsoDateInterval.class);
135
136  /**
137   * Lower limit for the range of the event date (date the occurrence was recorded).
138   *
139   * Included for backward compatibility as it mimicks the previous search behaviour:
140   * https://github.com/gbif/occurrence/issues/346
141   */
142  @Deprecated
143  public final static OccurrenceSearchParameter EVENT_DATE_GTE = new OccurrenceSearchParameter("EVENT_DATE_GTE", Date.class);
144
145  /**
146   * An identifier for the set of information associated with an Event (something that occurs at a place and time).
147   * Maybe a global unique identifier or an identifier specific to the data set.
148   */
149  public final static OccurrenceSearchParameter EVENT_ID = new OccurrenceSearchParameter("EVENT_ID", String.class);
150
151  /**
152   * An identifier for the broader Event that groups this and potentially other Events.
153   */
154  public final static OccurrenceSearchParameter PARENT_EVENT_ID = new OccurrenceSearchParameter("PARENT_EVENT_ID", String.class);
155
156  /**
157   * An identifier for an Event and its children events.
158   */
159  public final static OccurrenceSearchParameter EVENT_ID_HIERARCHY = new OccurrenceSearchParameter("EVENT_ID_HIERARCHY", String.class);
160
161  /**
162   * An identifier for the vocabulary-backed Event Type.
163   */
164  public final static OccurrenceSearchParameter EVENT_TYPE = new OccurrenceSearchParameter("EVENT_TYPE", String.class);
165
166  /**
167   * An identifier for the verbatim Event Type.
168   */
169  @Experimental
170  public final static OccurrenceSearchParameter VERBATIM_EVENT_TYPE = new OccurrenceSearchParameter("VERBATIM_EVENT_TYPE", String.class);
171
172  /**
173   * The name of, reference to, or description of the method or protocol used during an Event.
174   */
175  public final static OccurrenceSearchParameter SAMPLING_PROTOCOL = new OccurrenceSearchParameter("SAMPLING_PROTOCOL", String.class);
176
177  /**
178   * A list (concatenated and separated) of previous assignments of names to the organism.
179   */
180  public final static OccurrenceSearchParameter PREVIOUS_IDENTIFICATIONS = new OccurrenceSearchParameter("PREVIOUS_IDENTIFICATIONS", String.class);
181
182  /**
183   * Last interpreted date in ISO 8601 formats:yyyy, yyyy-MM, yyyy-MM-dd and MM-dd.
184   * This parameter accepts comma separated range values, examples of valid ranges are:
185   * <dl>
186   * <dt>2001-02-11,2010-01-10</dt>
187   * <dd>Dates between 2001-02-11 and 2010-01-10</dd>
188   * <dt>2001-02,2010-01</dt>
189   * <dd>Dates between first day of 2001-02 and last day of 2010-01</dd>
190   * <dt>2001,2010</dt>
191   * <dd>Dates between first day of 2001 and last day of 2010</dd>
192   * <dt>2001,2010-01</dt>
193   * <dd>Dates between first day of 2001 and last day of 2010-01</dd>
194   * <dt>2001-01-10,2010</dt>
195   * <dd>Dates between 2001-01-10 and last day of 2010</dd>
196   * <dt>2001-01-10,*</dt>
197   * <dd>Dates after 2001-01-10</dd>
198   * <dt>*,2001-01-10</dt>
199   * <dd>Dates before 2001-01-10</dd>
200   * <dt>*</dt>
201   * <dd>all dates</dd>
202   * </dl>
203   */
204  public final static OccurrenceSearchParameter LAST_INTERPRETED = new OccurrenceSearchParameter("LAST_INTERPRETED", Date.class);
205
206
207  /**
208   * Modified date in ISO 8601 formats:yyyy, yyyy-MM, yyyy-MM-dd and MM-dd.
209   * This parameter accepts comma separated range values, examples of valid ranges are:
210   * <dl>
211   * <dt>2001-02-11,2010-01-10</dt>
212   * <dd>Dates between 2001-02-11 and 2010-01-10</dd>
213   * <dt>2001-02,2010-01</dt>
214   * <dd>Dates between first day of 2001-02 and last day of 2010-01</dd>
215   * <dt>2001,2010</dt>
216   * <dd>Dates between first day of 2001 and last day of 2010</dd>
217   * <dt>2001,2010-01</dt>
218   * <dd>Dates between first day of 2001 and last day of 2010-01</dd>
219   * <dt>2001-01-10,2010</dt>
220   * <dd>Dates between 2001-01-10 and last day of 2010</dd>
221   * <dt>2001-01-10,*</dt>
222   * <dd>Dates after 2001-01-10</dd>
223   * <dt>*,2001-01-10</dt>
224   * <dd>Dates before 2001-01-10</dd>
225   * <dt>*</dt>
226   * <dd>all dates</dd>
227   * </dl>
228   */
229  public final static OccurrenceSearchParameter MODIFIED = new OccurrenceSearchParameter("MODIFIED", Date.class);
230
231  /**
232   * Latitude in decimals between -90 and 90 based on WGS 84.
233   */
234  public final static OccurrenceSearchParameter DECIMAL_LATITUDE = new OccurrenceSearchParameter("DECIMAL_LATITUDE", Double.class);
235
236  /**
237   * Longitude in decimals between -180 and 180 based on WGS 84.
238   */
239  public final static OccurrenceSearchParameter DECIMAL_LONGITUDE = new OccurrenceSearchParameter("DECIMAL_LONGITUDE", Double.class);
240
241  /**
242   * The uncertainty of the coordinate in meters.
243   * This parameter accepts comma separated range values, e.g.:
244   * <dl>
245   * <dt>*,100</dt>
246   * <dd>Uncertainty below or equals 100m</dd>
247   * <dt>10000,*</dt>
248   * <dd>Uncertainty above or equals 10,000m</dd>
249   * <dt>1000,5000</dt>
250   * <dd>Uncertainty between or equals 1000m and 5000m
251   * </dd>
252   * </dl>
253   */
254  public final static OccurrenceSearchParameter COORDINATE_UNCERTAINTY_IN_METERS = new OccurrenceSearchParameter("COORDINATE_UNCERTAINTY_IN_METERS", Double.class);
255
256  /**
257   * Country the occurrence was recorded in.
258   */
259  public final static OccurrenceSearchParameter COUNTRY = new OccurrenceSearchParameter("COUNTRY", Country.class);
260
261  /**
262   * GBIF region based on country
263   */
264  public final static OccurrenceSearchParameter GBIF_REGION = new OccurrenceSearchParameter("GBIF_REGION", GbifRegion.class);
265
266  /**
267   * Continent the occurrence was recorded in.
268   */
269  public final static OccurrenceSearchParameter CONTINENT = new OccurrenceSearchParameter("CONTINENT", Continent.class);
270
271  /**
272   * The country of the organization that publishes the dataset the occurrence belongs to.
273   */
274  public final static OccurrenceSearchParameter PUBLISHING_COUNTRY = new OccurrenceSearchParameter("PUBLISHING_COUNTRY", Country.class);
275
276  /**
277   * GBIF region based on publishibg country
278   */
279  public final static OccurrenceSearchParameter PUBLISHED_BY_GBIF_REGION = new OccurrenceSearchParameter("PUBLISHED_BY_GBIF_REGION", GbifRegion.class);
280
281  /**
282   * Altitude/elevation in meters above sea level.
283   * This parameter accepts comma separated range values, e.g.:
284   * <dl>
285   * <dt>*,100</dt>
286   * <dd>Altitude below or equals 100m</dd>
287   * <dt>100,*</dt>
288   * <dd>Altitude above or equals 100m</dd>
289   * <dt>-2,8.8</dt>
290   * <dd>Altitude between or equals -2m and 8.8m</dd>
291   * </dl>
292   */
293  public final static OccurrenceSearchParameter ELEVATION = new OccurrenceSearchParameter("ELEVATION", Double.class);
294
295  /**
296   * Depth in meters relative to altitude. For example 10 meters below a lake surface with given altitude.
297   * This parameter accepts comma separated range values, e.g.:
298   * <dl>
299   * <dt>*,10</dt>
300   * <dd>Depth below or equals 10m</dd>
301   * <dt>100,*</dt>
302   * <dd>Depth above or equals 100m</dd>
303   * <dt>12.1,28.8</dt>
304   * <dd>Depth between or equals 12.1m and 28.8m</dd>
305   * </dl>
306   */
307  public final static OccurrenceSearchParameter DEPTH = new OccurrenceSearchParameter("DEPTH", Double.class);
308
309  /**
310   * An identifier of any form assigned by the source to identify the institution
311   * the record belongs to. Not guaranteed to be unique.
312   */
313  public final static OccurrenceSearchParameter INSTITUTION_CODE = new OccurrenceSearchParameter("INSTITUTION_CODE", String.class);
314
315  /**
316   * An identifier of any form assigned by the source to identify the physical collection or digital dataset
317   * uniquely within the context of an institution.
318   */
319  public final static OccurrenceSearchParameter COLLECTION_CODE = new OccurrenceSearchParameter("COLLECTION_CODE", String.class);
320
321  /**
322   * An identifier of any form assigned by the source within a physical collection or digital dataset for the record
323   * which may not be unique, but should be fairly unique in combination with the institution and collection code.
324   */
325  public final static OccurrenceSearchParameter CATALOG_NUMBER = new OccurrenceSearchParameter("CATALOG_NUMBER", String.class);
326
327  /**
328   * The person who recorded the occurrence.
329   */
330  public final static OccurrenceSearchParameter RECORDED_BY = new OccurrenceSearchParameter("RECORDED_BY", String.class);
331
332  /**
333   * The person who identified the occurrence.
334   */
335  public final static OccurrenceSearchParameter IDENTIFIED_BY = new OccurrenceSearchParameter("IDENTIFIED_BY", String.class);
336
337  /**
338   * An identifier given to the Occurrence at the time it was recorded.
339   */
340  public final static OccurrenceSearchParameter RECORD_NUMBER = new OccurrenceSearchParameter("RECORD_NUMBER", String.class);
341
342  /**
343   * A basis of record enumeration value.
344   */
345  public final static OccurrenceSearchParameter BASIS_OF_RECORD = new OccurrenceSearchParameter("BASIS_OF_RECORD", BasisOfRecord.class);
346
347  /**
348   * The sex of the biological individual(s) represented in the occurrence.
349   */
350  public final static OccurrenceSearchParameter SEX = new OccurrenceSearchParameter("SEX", String.class);
351
352  /**
353   * Presents of associated sequences or an extension
354   */
355  public final static OccurrenceSearchParameter IS_SEQUENCED = new OccurrenceSearchParameter("IS_SEQUENCED", Boolean.class);
356
357  /**
358   * A taxon key from the GBIF backbone. All included and synonym taxa are included in the search, so a search for
359   * aves with taxonKey=212 will match all birds, no matter which species.
360   */
361  public final static OccurrenceSearchParameter TAXON_KEY = new OccurrenceSearchParameter("TAXON_KEY", String.class);
362
363  /**
364   * A taxon key from the GBIF backbone for the name usage of the currently valid or accepted taxon.
365   */
366  public final static OccurrenceSearchParameter ACCEPTED_TAXON_KEY = new OccurrenceSearchParameter("ACCEPTED_TAXON_KEY", String.class);
367
368  /**
369   * A kingdom key from the GBIF backbone.
370   */
371  public final static OccurrenceSearchParameter KINGDOM_KEY = new OccurrenceSearchParameter("KINGDOM_KEY", String.class);
372
373  /**
374   * A phylum key from the GBIF backbone.
375   */
376  public final static OccurrenceSearchParameter PHYLUM_KEY = new OccurrenceSearchParameter("PHYLUM_KEY", String.class);
377
378  /**
379   * A class key from the GBIF backbone.
380   */
381  public final static OccurrenceSearchParameter CLASS_KEY = new OccurrenceSearchParameter("CLASS_KEY", String.class);
382
383  /**
384   * A order key from the GBIF backbone.
385   */
386  public final static OccurrenceSearchParameter ORDER_KEY = new OccurrenceSearchParameter("ORDER_KEY", String.class);
387
388  /**
389   * A family key from the GBIF backbone.
390   */
391  public final static OccurrenceSearchParameter FAMILY_KEY = new OccurrenceSearchParameter("FAMILY_KEY", String.class);
392
393  /**
394   * A genus key from the GBIF backbone.
395   */
396  public final static OccurrenceSearchParameter GENUS_KEY = new OccurrenceSearchParameter("GENUS_KEY", String.class);
397
398  /**
399   * A subgenus key from the GBIF backbone.
400   */
401  public final static OccurrenceSearchParameter SUBGENUS_KEY = new OccurrenceSearchParameter("SUBGENUS_KEY", String.class);
402
403  /**
404   * A species key from the GBIF backbone.
405   */
406  public final static OccurrenceSearchParameter SPECIES_KEY = new OccurrenceSearchParameter("SPECIES_KEY", String.class);
407
408  /**
409   * Searches the interpreted, full scientific name of the occurrence.
410   */
411  public final static OccurrenceSearchParameter SCIENTIFIC_NAME = new OccurrenceSearchParameter("SCIENTIFIC_NAME", String.class);
412
413  /**
414   * Scientific name as provided byt the source.
415   */
416  public final static OccurrenceSearchParameter VERBATIM_SCIENTIFIC_NAME = new OccurrenceSearchParameter("VERBATIM_SCIENTIFIC_NAME", String.class);
417
418  /**
419   * Verbatim identifier for the set of taxon information. Maybe a global unique identifier or an identifier specific to
420   * the data set.
421   */
422  public final static OccurrenceSearchParameter TAXON_ID = new OccurrenceSearchParameter("TAXON_ID", String.class);
423
424  /**
425   * An identifier for the taxonomic concept to which the record refers - not for the nomenclatural details of a taxon.
426   */
427  public final static OccurrenceSearchParameter TAXON_CONCEPT_ID = new OccurrenceSearchParameter("TAXON_CONCEPT_ID", String.class);
428
429  /**
430   * The status of the use of the  GBIF Backbone taxonKey.
431   */
432  public final static OccurrenceSearchParameter TAXONOMIC_STATUS = new OccurrenceSearchParameter("TAXONOMIC_STATUS", TaxonomicStatus.class);
433
434  /**
435   * Searches for occurrence records which contain a value on its coordinate fields (latitude and longitude).
436   * HAS_COORDINATE=true searches for occurrence records with a coordinate value.
437   * HAS_COORDINATE=false searches for occurrence records without a coordinate value.
438   */
439  public final static OccurrenceSearchParameter HAS_COORDINATE = new OccurrenceSearchParameter("HAS_COORDINATE", Boolean.class);
440
441  /**
442   * Geometry in <a href="https://en.wikipedia.org/wiki/Well-known_text">Well Known Text</a> (WKT) format.
443   * E.g.: POLYGON ((30.0 10.0, 10.12 20.23, 20 40, 40 40, 30 10)).
444   * Multi geometries like MULTIPOLYGON are not supported and multiple parameters should be used instead.
445   * Valid geometries are:
446   * <ul>
447   * <li>POINT</li>
448   * <li>LINESTRING</li>
449   * <li>POLYGON</li>
450   * <li>LINEARRING</li>
451   * </ul>
452   */
453  public final static OccurrenceSearchParameter GEOMETRY = new OccurrenceSearchParameter("GEOMETRY", String.class);
454
455  /**
456   * Use in combination of LATITUDE and LONGITUDE parameters matches within a given distance.
457   * E.g.: geo_distance=100m,40,90 geo_distance=100km,40,90 geo_distance=100mi,40,90.
458   * See supported units in {@link org.gbif.api.model.occurrence.geo.DistanceUnit}.
459   */
460  public final static OccurrenceSearchParameter GEO_DISTANCE = new OccurrenceSearchParameter("GEO_DISTANCE", String.class);
461
462  /**
463   * The distance from a known centroid, e.g. a country centroid.
464   */
465  public final static OccurrenceSearchParameter DISTANCE_FROM_CENTROID_IN_METERS = new OccurrenceSearchParameter("DISTANCE_FROM_CENTROID_IN_METERS", Double.class);
466
467  /**
468   * Includes/excludes occurrence records which contain geospatial issues for their coordinate.
469   * See {@link org.gbif.api.vocabulary.OccurrenceIssue#GEOSPATIAL_RULES}
470   * HAS_GEOSPATIAL_ISSUE=true include records with spatial issues.
471   * HAS_GEOSPATIAL_ISSUE=false exclude records with spatial issues.
472   * The absence of this parameter returns any record with or without spatial issues.
473   */
474  public final static OccurrenceSearchParameter HAS_GEOSPATIAL_ISSUE = new OccurrenceSearchParameter("HAS_GEOSPATIAL_ISSUE", Boolean.class);
475
476  /**
477   * Searches occurrence for those that have a specific issue.
478   */
479  public final static OccurrenceSearchParameter ISSUE = new OccurrenceSearchParameter("ISSUE", OccurrenceIssue.class);
480
481  /**
482   * Searches occurrence for those that have a specific taxonomic issue. This is separated out from the general issue
483   * field as taxonomic issues will be tied to a specific checklist.
484   */
485  public final static OccurrenceSearchParameter TAXONOMIC_ISSUE = new OccurrenceSearchParameter("TAXONOMIC_ISSUE", String.class);
486
487  /**
488   * Nomenclatural type (type status, typified scientific name, publication) applied to the subject.
489   */
490  public final static OccurrenceSearchParameter TYPE_STATUS = new OccurrenceSearchParameter("TYPE_STATUS", String.class);
491
492  /**
493   * The kind of media object.
494   * Recommended terms from the DCMI Type Vocabulary are StillImage, Sound or MovingImage for GBIF to index and show the
495   * media files.
496   */
497  public final static OccurrenceSearchParameter MEDIA_TYPE = new OccurrenceSearchParameter("MEDIA_TYPE", MediaType.class);
498
499  /**
500   *  An identifier for the Occurrence (as opposed to a particular digital record of the occurrence).
501   *  In the absence of a persistent global unique identifier, construct one from a combination of identifiers in the
502   *  record that will most closely make the occurrenceID globally unique.
503   */
504  public final static OccurrenceSearchParameter OCCURRENCE_ID = new OccurrenceSearchParameter("OCCURRENCE_ID", String.class);
505
506  /**
507   * The process by which the biological individual(s) represented in the Occurrence became established at the location.
508   */
509  public final static OccurrenceSearchParameter ESTABLISHMENT_MEANS = new OccurrenceSearchParameter("ESTABLISHMENT_MEANS", String.class);
510
511  /**
512   * Provides the controlled vocabulary for information about degree to which an Organism survives, reproduces, and expands its range at the given place and time.
513   */
514  public final static OccurrenceSearchParameter DEGREE_OF_ESTABLISHMENT = new OccurrenceSearchParameter("DEGREE_OF_ESTABLISHMENT", String.class);
515
516  /**
517   * Provides the controlled vocabulary for information about the process by which an Organism came to be in a given place at a given time.
518   * The pathway of an organism or organisms have been introduced to a given place and time.
519   */
520  public final static OccurrenceSearchParameter PATHWAY = new OccurrenceSearchParameter("PATHWAY", String.class);
521
522  /**
523   * Searches for records whose publishing country is different to the country where the record was recorded in.
524   */
525  public final static OccurrenceSearchParameter REPATRIATED = new OccurrenceSearchParameter("REPATRIATED", Boolean.class);
526
527  /**
528   * An identifier for the Organism instance (as opposed to a particular digital record of the Organism).
529   * May be a globally unique identifier or an identifier specific to the data set.
530   */
531  public final static OccurrenceSearchParameter ORGANISM_ID = new OccurrenceSearchParameter("ORGANISM_ID", String.class);
532
533  /**
534   * The name of the next smaller administrative region than country in which the Location occurs.
535   */
536  public final static OccurrenceSearchParameter STATE_PROVINCE = new OccurrenceSearchParameter("STATE_PROVINCE", String.class);
537
538  /**
539   * The name of the water body in which the Location occurs.
540   */
541  public final static OccurrenceSearchParameter WATER_BODY = new OccurrenceSearchParameter("WATER_BODY", String.class);
542
543  /**
544   * The specific description of the place.
545   * It may contain information modified from the original to correct perceived errors or standardize the description.
546   */
547  public final static OccurrenceSearchParameter LOCALITY = new OccurrenceSearchParameter("LOCALITY", String.class);
548
549  /**
550   * Protocol used to provide the occurrence record.
551   */
552  public final static OccurrenceSearchParameter PROTOCOL = new OccurrenceSearchParameter("PROTOCOL", EndpointType.class);
553
554  /**
555   * The license applied to the dataset.
556   */
557  public final static OccurrenceSearchParameter LICENSE = new OccurrenceSearchParameter("LICENSE", License.class);
558
559  /**
560   * The owning organizations uuid key.
561   */
562  public final static OccurrenceSearchParameter PUBLISHING_ORG = new OccurrenceSearchParameter("PUBLISHING_ORG", UUID.class);
563
564  /**
565   * The GBIF network that the publishing organisation belongs to.
566   */
567  public final static OccurrenceSearchParameter NETWORK_KEY = new OccurrenceSearchParameter("NETWORK_KEY", UUID.class);
568
569  /**
570   * The technical installation key that hosts/publishes this record.
571   */
572  public final static OccurrenceSearchParameter INSTALLATION_KEY = new OccurrenceSearchParameter("INSTALLATION_KEY", UUID.class);
573
574  /**
575   * The organization key of the installation that hosts this record.
576   */
577  public final static OccurrenceSearchParameter HOSTING_ORGANIZATION_KEY = new OccurrenceSearchParameter("HOSTING_ORGANIZATION_KEY", UUID.class);
578
579  /**
580   * Crawl attempt that harvested this record.
581   */
582  public final static OccurrenceSearchParameter CRAWL_ID = new OccurrenceSearchParameter("CRAWL_ID", Integer.class);
583
584  /**
585   * GBIF ProjectId.
586   */
587  public final static OccurrenceSearchParameter PROJECT_ID = new OccurrenceSearchParameter("PROJECT_ID", String.class);
588
589  /**
590   * GBIF Programme Acronym.
591   */
592  public final static OccurrenceSearchParameter PROGRAMME = new OccurrenceSearchParameter("PROGRAMME", String.class);
593
594  /**
595   * A number or enumeration value for the quantity of organisms.
596   */
597  public final static OccurrenceSearchParameter ORGANISM_QUANTITY = new OccurrenceSearchParameter("ORGANISM_QUANTITY", Double.class);
598
599  /**
600   * The type of quantification system used for the quantity of organisms.
601   */
602  public final static OccurrenceSearchParameter ORGANISM_QUANTITY_TYPE = new OccurrenceSearchParameter("ORGANISM_QUANTITY_TYPE", String.class);
603
604  /**
605   * The unit of measurement of the size (time duration, length, area, or volume) of a sample in a sampling event.
606   */
607  public final static OccurrenceSearchParameter SAMPLE_SIZE_UNIT = new OccurrenceSearchParameter("SAMPLE_SIZE_UNIT", String.class);
608
609  /**
610   * A numeric value for a measurement of the size (time duration, length, area, or volume) of a sample in a sampling event.
611   */
612  public final static OccurrenceSearchParameter SAMPLE_SIZE_VALUE = new OccurrenceSearchParameter("SAMPLE_SIZE_VALUE", Double.class);
613
614  /**
615   * Calculated organismQuantity relative to the sampleSizeValue i.e. -> organismQuantity / sampleSizeValue.
616   */
617  public final static OccurrenceSearchParameter RELATIVE_ORGANISM_QUANTITY = new OccurrenceSearchParameter("RELATIVE_ORGANISM_QUANTITY", Double.class);
618
619  /**
620   * Collection key. It links to the collection to which this record belongs.
621   */
622  public final static OccurrenceSearchParameter COLLECTION_KEY = new OccurrenceSearchParameter("COLLECTION_KEY", String.class);
623
624  /**
625   * Institution key. It links to the institution that maintains, recorded or digitized  this record.
626   */
627  public final static OccurrenceSearchParameter INSTITUTION_KEY = new OccurrenceSearchParameter("INSTITUTION_KEY", String.class);
628
629  /**
630   * Agent identifiers from GbifTerm.recordedByID
631   */
632  public final static OccurrenceSearchParameter RECORDED_BY_ID = new OccurrenceSearchParameter("RECORDED_BY_ID", String.class);
633
634  /**
635   * Agent identifiers from GbifTerm.identifiedByID
636   */
637  public final static OccurrenceSearchParameter IDENTIFIED_BY_ID = new OccurrenceSearchParameter("IDENTIFIED_BY_ID", String.class);
638
639  /**
640   * An occurrence status enumeration value.
641   */
642  public final static OccurrenceSearchParameter OCCURRENCE_STATUS = new OccurrenceSearchParameter("OCCURRENCE_STATUS", OccurrenceStatus.class);
643
644  /**
645   * A <a href="https://gadm.org">GADM</a> identifier at any level.
646   */
647  public final static OccurrenceSearchParameter GADM_GID = new OccurrenceSearchParameter("GADM_GID", String.class);
648
649  /**
650   * A <a href="https://gadm.org">GADM</a> country, island or territory (level zero) identifier.
651   */
652  public final static OccurrenceSearchParameter GADM_LEVEL_0_GID = new OccurrenceSearchParameter("GADM_LEVEL_0_GID", String.class);
653
654  /**
655   * A <a href="https://gadm.org">GADM</a> first-level identifier.
656   */
657  public final static OccurrenceSearchParameter GADM_LEVEL_1_GID = new OccurrenceSearchParameter("GADM_LEVEL_1_GID", String.class);
658
659  /**
660   * A <a href="https://gadm.org">GADM</a> second-level identifier.
661   */
662  public final static OccurrenceSearchParameter GADM_LEVEL_2_GID = new OccurrenceSearchParameter("GADM_LEVEL_2_GID", String.class);
663
664  /**
665   * A <a href="https://gadm.org">GADM</a> third-level identifier.
666   */
667  public final static OccurrenceSearchParameter GADM_LEVEL_3_GID = new OccurrenceSearchParameter("GADM_LEVEL_3_GID", String.class);
668
669  /**
670   * The life stage of an occurrence.
671   */
672  public final static OccurrenceSearchParameter LIFE_STAGE = new OccurrenceSearchParameter("LIFE_STAGE", String.class);
673
674  /**
675   * Searches for occurrences that are clustered.
676   */
677  public final static OccurrenceSearchParameter IS_IN_CLUSTER = new OccurrenceSearchParameter("IS_IN_CLUSTER", Boolean.class);
678
679  /**
680   * Searches for occurrences that have a particular DwC-A extension.
681   */
682  public final static OccurrenceSearchParameter DWCA_EXTENSION = new OccurrenceSearchParameter("DWCA_EXTENSION", String.class);
683
684  /**
685   * Searches for occurrences that have a IUCN Red List Category.
686   */
687  public final static OccurrenceSearchParameter IUCN_RED_LIST_CATEGORY = new OccurrenceSearchParameter("IUCN_RED_LIST_CATEGORY", String.class);
688
689  /**
690   * The dwc dataset id.
691   */
692  public final static OccurrenceSearchParameter DATASET_ID = new OccurrenceSearchParameter("DATASET_ID", String.class);
693
694  /**
695   * The dwc dataset name.
696   */
697  public final static OccurrenceSearchParameter DATASET_NAME = new OccurrenceSearchParameter("DATASET_NAME", String.class);
698
699  /**
700   * Other catalog numbers associated to an occurrence.
701   */
702  public final static OccurrenceSearchParameter OTHER_CATALOG_NUMBERS = new OccurrenceSearchParameter("OTHER_CATALOG_NUMBERS", String.class);
703
704  /**
705   * Preparations methods of an occurrence.
706   */
707  public final static OccurrenceSearchParameter PREPARATIONS = new OccurrenceSearchParameter("PREPARATIONS", String.class);
708
709  /**
710   * The name of the island on or near which the location occurs.
711   */
712  public final static OccurrenceSearchParameter ISLAND = new OccurrenceSearchParameter("ISLAND", String.class);
713
714  /**
715   * The name of the island group in which the location occurs.
716   */
717  public final static OccurrenceSearchParameter ISLAND_GROUP = new OccurrenceSearchParameter("ISLAND_GROUP", String.class);
718
719  /**
720   * A list (concatenated and separated) of names of people, groups, or organizations who determined the georeference
721   * (spatial representation) for the location.
722   */
723  public final static OccurrenceSearchParameter GEOREFERENCED_BY = new OccurrenceSearchParameter("GEOREFERENCED_BY", String.class);
724
725  /**
726   * A list (concatenated and separated) of geographic names less specific than the information captured in the locality
727   * term.
728   */
729  public final static OccurrenceSearchParameter HIGHER_GEOGRAPHY = new OccurrenceSearchParameter("HIGHER_GEOGRAPHY", String.class);
730
731  /**
732   *    An identifier given to the event in the field. Often serves as a link between field notes and the event.
733   */
734  public final static OccurrenceSearchParameter FIELD_NUMBER = new OccurrenceSearchParameter("FIELD_NUMBER", String.class);
735
736  /**
737   * The full name of the earliest possible geochronologic eon or lowest chrono-stratigraphic eonothem or the informal
738   * name ("Precambrian") attributable to the stratigraphic horizon from which the MaterialEntity was collected.
739   */
740  public final static OccurrenceSearchParameter EARLIEST_EON_OR_LOWEST_EONOTHEM = new OccurrenceSearchParameter("EARLIEST_EON_OR_LOWEST_EONOTHEM", String.class);
741
742  /**
743   * The full name of the latest possible geochronologic eon or highest chrono-stratigraphic eonothem or the informal
744   * name ("Precambrian") attributable to the stratigraphic horizon from which the MaterialEntity was collected.
745   */
746  public final static OccurrenceSearchParameter LATEST_EON_OR_HIGHEST_EONOTHEM = new OccurrenceSearchParameter("LATEST_EON_OR_HIGHEST_EONOTHEM", String.class);
747
748  /**
749   * The full name of the earliest possible geochronologic era or lowest chronostratigraphic erathem attributable to the
750   * stratigraphic horizon from which the MaterialEntity was collected.
751   */
752  public final static OccurrenceSearchParameter EARLIEST_ERA_OR_LOWEST_ERATHEM = new OccurrenceSearchParameter("EARLIEST_ERA_OR_LOWEST_ERATHEM", String.class);
753
754  /**
755   * The full name of the latest possible geochronologic era or highest chronostratigraphic erathem attributable to the
756   * stratigraphic horizon from which the MaterialEntity was collected.
757   */
758  public final static OccurrenceSearchParameter LATEST_ERA_OR_HIGHEST_ERATHEM = new OccurrenceSearchParameter("LATEST_ERA_OR_HIGHEST_ERATHEM", String.class);
759
760  /**
761   * The full name of the earliest possible geochronologic period or lowest chronostratigraphic system attributable to
762   * the stratigraphic horizon from which the MaterialEntity was collected.
763   */
764  public final static OccurrenceSearchParameter EARLIEST_PERIOD_OR_LOWEST_SYSTEM = new OccurrenceSearchParameter("EARLIEST_PERIOD_OR_LOWEST_SYSTEM", String.class);
765
766  /**
767   * The full name of the latest possible geochronologic period or highest chronostratigraphic system attributable to
768   * the stratigraphic horizon from which the MaterialEntity was collected.
769   */
770  public final static OccurrenceSearchParameter LATEST_PERIOD_OR_HIGHEST_SYSTEM = new OccurrenceSearchParameter("LATEST_PERIOD_OR_HIGHEST_SYSTEM", String.class);
771
772  /**
773   * The full name of the earliest possible geochronologic epoch or lowest chronostratigraphic series attributable to
774   * the stratigraphic horizon from which the MaterialEntity was collected.
775   */
776  public final static OccurrenceSearchParameter EARLIEST_EPOCH_OR_LOWEST_SERIES = new OccurrenceSearchParameter("EARLIEST_EPOCH_OR_LOWEST_SERIES", String.class);
777
778  /**
779   * The full name of the latest possible geochronologic epoch or highest chronostratigraphic series attributable to the
780   * stratigraphic horizon from which the MaterialEntity was collected.
781   */
782  public final static OccurrenceSearchParameter LATEST_EPOCH_OR_HIGHEST_SERIES = new OccurrenceSearchParameter("LATEST_EPOCH_OR_HIGHEST_SERIES", String.class);
783
784  /**
785   * The full name of the earliest possible geochronologic age or lowest chronostratigraphic stage attributable to the
786   * stratigraphic horizon from which the MaterialEntity was collected.
787   */
788  public final static OccurrenceSearchParameter EARLIEST_AGE_OR_LOWEST_STAGE = new OccurrenceSearchParameter("EARLIEST_AGE_OR_LOWEST_STAGE", String.class);
789
790  /**
791   * The full name of the latest possible geochronologic age or highest chronostratigraphic stage attributable to the
792   * stratigraphic horizon from which the MaterialEntity was collected.
793   */
794  public final static OccurrenceSearchParameter LATEST_AGE_OR_HIGHEST_STAGE = new OccurrenceSearchParameter("LATEST_AGE_OR_HIGHEST_STAGE", String.class);
795
796  /**
797   * The full name of the lowest possible geological biostratigraphic zone of the stratigraphic horizon from which the
798   * MaterialEntity was collected.
799   */
800  public final static OccurrenceSearchParameter LOWEST_BIOSTRATIGRAPHIC_ZONE = new OccurrenceSearchParameter("LOWEST_BIOSTRATIGRAPHIC_ZONE", String.class);
801
802  /**
803   * The full name of the highest possible geological biostratigraphic zone of the stratigraphic horizon from which the
804   * MaterialEntity was collected.
805   */
806  public final static OccurrenceSearchParameter HIGHEST_BIOSTRATIGRAPHIC_ZONE = new OccurrenceSearchParameter("HIGHEST_BIOSTRATIGRAPHIC_ZONE", String.class);
807
808  /**
809   * The full name of the lithostratigraphic group from which the MaterialEntity was collected.
810   */
811  public final static OccurrenceSearchParameter GROUP = new OccurrenceSearchParameter("GROUP", String.class);
812
813  /**
814   * The full name of the lithostratigraphic formation from which the MaterialEntity was collected.
815   */
816  public final static OccurrenceSearchParameter FORMATION = new OccurrenceSearchParameter("FORMATION", String.class);
817
818  /**
819   * The full name of the lithostratigraphic member from which the MaterialEntity was collected.
820   */
821  public final static OccurrenceSearchParameter MEMBER = new OccurrenceSearchParameter("MEMBER", String.class);
822
823  /**
824   * The full name of the lithostratigraphic bed from which the MaterialEntity was collected.
825   */
826  public final static OccurrenceSearchParameter BED = new OccurrenceSearchParameter("BED", String.class);
827
828  /**
829   * A list (concatenated and separated) of identifiers (publication, global unique identifier, URI) of
830   * genetic sequence information associated with the material entity.
831   */
832  public final static OccurrenceSearchParameter ASSOCIATED_SEQUENCES = new OccurrenceSearchParameter("ASSOCIATED_SEQUENCES", String.class);
833
834  /**
835   * Unique GBIF key for the occurrence.
836   */
837  public final static OccurrenceSearchParameter GBIF_ID = new OccurrenceSearchParameter("GBIF_ID", String.class);
838
839  /**
840   * Geological time of an occurrence that searchs in the chronostratigraphy fields.
841   */
842  public final static OccurrenceSearchParameter GEOLOGICAL_TIME = new OccurrenceSearchParameter("GEOLOGICAL_TIME", String.class);
843
844  /**
845   * Searches in the lithostratigraphy fields(bed, formation, group, member).
846   */
847  public final static OccurrenceSearchParameter LITHOSTRATIGRAPHY = new OccurrenceSearchParameter("LITHOSTRATIGRAPHY", String.class);
848
849  /**
850   * Searches in the biostratigraphy fields(lowest and highest biostratigraphy).
851   */
852  public final static OccurrenceSearchParameter BIOSTRATIGRAPHY = new OccurrenceSearchParameter("BIOSTRATIGRAPHY", String.class);
853
854  /**
855   * @return the data type expected for the value of the respective search parameter
856   */
857  public final static OccurrenceSearchParameter DNA_SEQUENCE_ID = new OccurrenceSearchParameter("DNA_SEQUENCE_ID", String.class);
858
859
860  public static OccurrenceSearchParameter[] values(){
861
862    Field[] values = OccurrenceSearchParameter.class.getFields();
863    List<OccurrenceSearchParameter> c = new ArrayList<>();
864    for (Field field: values) {
865      try {
866        c.add((OccurrenceSearchParameter) field.get(OccurrenceSearchParameter.class));
867      } catch (IllegalAccessException e) {
868        throw new RuntimeException(e);
869      }
870    }
871    return c.toArray(new OccurrenceSearchParameter[0]);
872  }
873
874  private Class<?> type;
875  private String name;
876
877  public OccurrenceSearchParameter() {}
878
879  public OccurrenceSearchParameter(String name, Class<?> type) {
880    this.name = name;
881    this.type = type;
882  }
883
884  @Override
885  public String name() {
886    return this.name;
887  }
888
889  public Class<?> getType() {
890    return type;
891  }
892
893  public String getName() {
894    return name;
895  }
896
897  @Override
898  public Class<?> type() {
899    return this.type;
900  }
901
902  @Override
903  public String toString() {
904    return name;
905  }
906
907  @Override
908  public boolean equals(Object o) {
909    if (this == o) return true;
910    if (o == null || getClass() != o.getClass()) return false;
911    OccurrenceSearchParameter that = (OccurrenceSearchParameter) o;
912    return Objects.equals(type, that.type) && Objects.equals(name, that.name);
913  }
914
915  @JsonValue
916  public String getSerializedValue() {
917    return name;
918  }
919
920  @Override
921  public int hashCode() {
922    return Objects.hash(type, name);
923  }
924
925  /**
926   * Lookup a parameter by its name.
927   * @param name the name of the parameter
928   * @return the parameter if found, otherwise empty
929   */
930  public static Optional<OccurrenceSearchParameter> lookup(String name) {
931    String normedType = name.toUpperCase().replaceAll("[. _-]", "");
932    java.lang.reflect.Field[] values = OccurrenceSearchParameter.class.getFields();
933    for (Field field: values) {
934
935      String fieldName = field.getName();
936      String normedVal = fieldName.replaceAll("[. _-]", "");
937      if (normedType.equals(normedVal)) {
938        try {
939          return Optional.of((OccurrenceSearchParameter) field.get(OccurrenceSearchParameter.class));
940        } catch (IllegalAccessException e) {
941          throw new RuntimeException(e);
942        }
943      }
944    }
945    return Optional.empty();
946  }
947
948  public static class OccurrenceSearchParameterKeyDeserializer extends KeyDeserializer {
949
950    @Override
951    public Object deserializeKey(String value, DeserializationContext deserializationContext) throws IOException {
952      Field[] values = OccurrenceSearchParameter.class.getFields();
953      try {
954        for (Field field: values) {
955          if (field.getName().equalsIgnoreCase(value)) {
956            return (OccurrenceSearchParameter) field.get(OccurrenceSearchParameter.class);
957          }
958        }
959      } catch (IllegalAccessException e) {
960        // DO NOTHING
961      }
962      return null;
963    }
964  }
965
966  public static class OccurrenceSearchParameterDeserializer extends JsonDeserializer<OccurrenceSearchParameter> {
967
968    @Override
969    public OccurrenceSearchParameter deserialize(com.fasterxml.jackson.core.JsonParser jsonParser, com.fasterxml.jackson.databind.DeserializationContext deserializationContext) throws IOException, JacksonException {
970
971      Field[] values = OccurrenceSearchParameter.class.getFields();
972      try {
973        String value = jsonParser.getText();
974        for (Field field: values) {
975          if (field.getName().equalsIgnoreCase(value)) {
976            return (OccurrenceSearchParameter) field.get(OccurrenceSearchParameter.class);
977          }
978        }
979
980      } catch (IllegalAccessException e) {
981        // DO NOTHING
982      }
983
984      try {
985        ObjectNode node = jsonParser.getCodec().readTree(jsonParser);
986        String value = node.get("name").asText();
987        for (Field field: values) {
988          if (field.getName().equalsIgnoreCase(value)) {
989            return (OccurrenceSearchParameter) field.get(OccurrenceSearchParameter.class);
990          }
991        }
992      } catch (Exception e) {
993        // DO NOTHING
994      }
995
996      return null;
997    }
998  }
999}