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}