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;
015
016import io.swagger.v3.oas.annotations.Hidden;
017import io.swagger.v3.oas.annotations.media.Schema;
018
019import org.gbif.api.jackson.DownloadRequestSerde;
020import org.gbif.api.vocabulary.Extension;
021
022import java.io.Serializable;
023import java.util.Collection;
024import java.util.Collections;
025import java.util.HashSet;
026import java.util.Objects;
027import java.util.Set;
028import java.util.StringJoiner;
029import java.util.stream.Collectors;
030import java.util.stream.Stream;
031
032import javax.annotation.Nullable;
033
034import org.apache.commons.lang3.StringUtils;
035
036import com.fasterxml.jackson.annotation.JsonIgnore;
037import com.fasterxml.jackson.annotation.JsonProperty;
038import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
039
040/**
041 * Represents a request to download occurrence records.
042 * This is the base class for specific type of downloads: predicate based downloads and SQL downloads.
043 */
044@SuppressWarnings("unused")
045@JsonDeserialize(using = DownloadRequestSerde.class)
046public abstract class DownloadRequest implements Serializable {
047
048  private static final String DELIMITER = ",";
049
050  @Schema(
051    description = "The GBIF username of the initiator of the download request."
052  )
053  @JsonProperty("creator")
054  private String creator;
055
056  @Schema(
057    description = "A list of email addresses to notify when the download finishes."
058  )
059  @JsonProperty("notificationAddresses")
060  private Set<String> notificationAddresses;
061
062  @Schema(
063    description = "Whether to send a notification email when the download finishes."
064  )
065  @JsonProperty("sendNotification")
066  private Boolean sendNotification;
067
068  @Schema(
069    description = "The data format of the download."
070  )
071  @JsonProperty("format")
072  private DownloadFormat format;
073
074  @Hidden
075  @JsonProperty("type")
076  private DownloadType type;
077
078  @Hidden
079  @JsonProperty("verbatimExtensions")
080  private Set<Extension> verbatimExtensions;
081
082  /**
083   * Default constructor.
084   */
085  public DownloadRequest() {
086    // Empty constructor required to create instances from the data access layer.
087  }
088
089  public DownloadRequest(String creator, Collection<String> notificationAddresses,
090                         Boolean sendNotification, DownloadFormat format,
091                         DownloadType downloadType,
092                         Set<Extension> verbatimExtensions
093  ) {
094    this.creator = creator;
095    this.notificationAddresses = notificationAddresses == null ? Collections.emptySet() :
096      Collections.unmodifiableSet(new HashSet<>(notificationAddresses));
097    this.sendNotification = sendNotification;
098    this.format = format;
099    this.type = downloadType;
100    this.verbatimExtensions = verbatimExtensions == null? Collections.emptySet(): verbatimExtensions;
101  }
102
103  /**
104   * @return the user account that initiated the download
105   */
106  @Nullable
107  public String getCreator() {
108    return creator;
109  }
110
111  /**
112   * @return set of email addresses for notifications
113   */
114  @Nullable
115  public Set<String> getNotificationAddresses() {
116    return notificationAddresses;
117  }
118
119  /**
120   * Returns the notification addresses as single string. The emails are separated by ','.
121   */
122  @Nullable
123  @JsonIgnore
124  public String getNotificationAddressesAsString() {
125    if (notificationAddresses != null) {
126      return notificationAddresses.stream()
127        .filter(Objects::nonNull)
128        .map(String::trim)
129        .collect(Collectors.joining(DELIMITER));
130    }
131    return null;
132  }
133
134  public void setCreator(String creator) {
135    this.creator = creator;
136  }
137
138  public void setNotificationAddresses(Set<String> notificationAddresses) {
139    this.notificationAddresses = notificationAddresses;
140  }
141
142  /**
143   * Sets the notificationAddresses using a single String value that is split by ','.
144   */
145  public void setNotificationAddressesAsString(String notificationAddressesAsString) {
146    if (notificationAddressesAsString != null) {
147      notificationAddresses = Stream.of(notificationAddressesAsString.split(DELIMITER))
148        .filter(StringUtils::isNotEmpty)
149        .map(String::trim)
150        .collect(Collectors.toSet());
151    }
152  }
153
154  @Nullable
155  public Boolean getSendNotification() {
156    return sendNotification;
157  }
158
159  /**
160   * This parameter determines if the requested download must be notified to the created once it's ready.
161   */
162  public void setSendNotification(boolean sendNotification) {
163    this.sendNotification = sendNotification;
164  }
165
166  public DownloadFormat getFormat() {
167    return format;
168  }
169
170  /**
171   * This parameter determines the output format of the requested download.
172   */
173  public void setFormat(DownloadFormat format) {
174    this.format = format;
175  }
176
177  public DownloadType getType() {
178    return type;
179  }
180
181  /**
182   * Download type: Occurrence or Event.
183   */
184  public void setType(DownloadType type) {
185    this.type = type;
186  }
187
188  /**
189   * Requested verbatimExtensions for this download.
190   */
191  @Nullable
192  public Set<Extension> getVerbatimExtensions() {
193    return verbatimExtensions;
194  }
195
196  public void setVerbatimExtensions(Set<Extension> verbatimExtensions) {
197    this.verbatimExtensions = verbatimExtensions;
198  }
199
200  @Override
201  public boolean equals(Object o) {
202    if (this == o) {
203      return true;
204    }
205    if (o == null || getClass() != o.getClass()) {
206      return false;
207    }
208    DownloadRequest that = (DownloadRequest) o;
209    return sendNotification == that.sendNotification &&
210      Objects.equals(creator, that.creator) &&
211      Objects.equals(notificationAddresses, that.notificationAddresses) &&
212      format == that.format &&
213      type == that.type &&
214      Objects.equals(verbatimExtensions, that.verbatimExtensions);
215  }
216
217  @Override
218  public int hashCode() {
219    return Objects.hash(creator, notificationAddresses, sendNotification, format, type, verbatimExtensions);
220  }
221
222  @Override
223  public String toString() {
224    return new StringJoiner(", ", DownloadRequest.class.getSimpleName() + "[", "]")
225      .add("creator='" + creator + "'")
226      .add("notificationAddresses=" + notificationAddresses)
227      .add("sendNotification=" + sendNotification)
228      .add("format=" + format)
229      .add("type=" + type)
230      .add("verbatimExtensions=" + verbatimExtensions)
231      .toString();
232  }
233}