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.ArraySchema;
018import io.swagger.v3.oas.annotations.media.Schema;
019
020import org.gbif.api.jackson.DownloadRequestSerde;
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@Schema(
045  description = "An occurrence download request.",
046  oneOf = {PredicateDownloadRequest.class, SqlDownloadRequest.class}
047)
048@SuppressWarnings("unused")
049@JsonDeserialize(using = DownloadRequestSerde.class)
050public abstract class DownloadRequest implements Serializable {
051
052  private static final String DELIMITER = ",";
053
054  @Schema(
055    description = "The GBIF username of the initiator of the download request."
056  )
057  @JsonProperty("creator")
058  private String creator;
059
060  @ArraySchema(
061    schema = @Schema(
062      description = "An email addresses to notify when the download finishes."
063    )
064  )
065  @JsonProperty("notificationAddresses")
066  private Set<String> notificationAddresses;
067
068  @Schema(
069    description = "Whether to send a notification email when the download finishes."
070  )
071  @JsonProperty("sendNotification")
072  private Boolean sendNotification;
073
074  @Schema(
075    description = "The data format of the download."
076  )
077  @JsonProperty("format")
078  private DownloadFormat format;
079
080  @Hidden
081  @JsonProperty("type")
082  private DownloadType type;
083
084  /**
085   * Default constructor.
086   */
087  public DownloadRequest() {
088    // Empty constructor required to create instances from the data access layer.
089  }
090
091  public DownloadRequest(String creator, Collection<String> notificationAddresses,
092                         Boolean sendNotification, DownloadFormat format,
093                         DownloadType downloadType
094  ) {
095    this.creator = creator;
096    this.notificationAddresses = notificationAddresses == null ? Collections.emptySet() :
097      Collections.unmodifiableSet(new HashSet<>(notificationAddresses));
098    this.sendNotification = sendNotification;
099    this.format = format;
100    this.type = downloadType;
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  public void setCreator(String creator) {
112    this.creator = creator;
113  }
114
115  /**
116   * @return set of email addresses for notifications
117   */
118  @Nullable
119  public Set<String> getNotificationAddresses() {
120    return notificationAddresses;
121  }
122
123  public void setNotificationAddresses(Set<String> notificationAddresses) {
124    this.notificationAddresses = notificationAddresses;
125  }
126
127  /**
128   * Returns the notification addresses as single string. The emails are separated by ','.
129   */
130  @Nullable
131  @JsonIgnore
132  public String getNotificationAddressesAsString() {
133    if (notificationAddresses != null) {
134      return notificationAddresses.stream()
135        .filter(Objects::nonNull)
136        .map(String::trim)
137        .collect(Collectors.joining(DELIMITER));
138    }
139    return null;
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  @JsonIgnore
189  public String getFileExtension() {
190    return format.getExtension();
191  }
192
193  @Override
194  public boolean equals(Object o) {
195    if (this == o) {
196      return true;
197    }
198    if (o == null || getClass() != o.getClass()) {
199      return false;
200    }
201    DownloadRequest that = (DownloadRequest) o;
202    return sendNotification == that.sendNotification &&
203      Objects.equals(creator, that.creator) &&
204      Objects.equals(notificationAddresses, that.notificationAddresses) &&
205      format == that.format &&
206      type == that.type;
207  }
208
209  @Override
210  public int hashCode() {
211    return Objects.hash(creator, notificationAddresses, sendNotification, format, type);
212  }
213
214  @Override
215  public String toString() {
216    return new StringJoiner(", ", DownloadRequest.class.getSimpleName() + "[", "]")
217      .add("creator='" + creator + "'")
218      .add("notificationAddresses=" + notificationAddresses)
219      .add("sendNotification=" + sendNotification)
220      .add("format=" + format)
221      .add("type=" + type)
222      .toString();
223  }
224}