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