001/* 002 * Copyright 2020 Global Biodiversity Information Facility (GBIF) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.gbif.api.model.registry; 017 018import org.gbif.api.vocabulary.InstallationType; 019 020import java.util.ArrayList; 021import java.util.Date; 022import java.util.List; 023import java.util.Objects; 024import java.util.StringJoiner; 025import java.util.UUID; 026 027import javax.annotation.Nullable; 028import javax.validation.constraints.NotNull; 029import javax.validation.constraints.Null; 030 031import com.fasterxml.jackson.annotation.JsonIgnore; 032 033import io.swagger.v3.oas.annotations.media.Schema; 034 035/** 036 * A technical installation which can serve datasets. 037 * Note: An Installation may be marked as disabled, meaning that some process has identified it is out of action. 038 * For the GBIF crawling infrastructure, this means it will not be "metasynced" nor will any dataset associated be 039 * eligible for crawling. 040 */ 041// TODO: Only allow adding of Endpoints of the correct type. 042@Schema( 043 description = "A technical installation which can serve datasets." 044) 045@SuppressWarnings("unused") 046public class Installation 047 implements NetworkEntity, 048 Contactable, 049 Endpointable, 050 MachineTaggable, 051 Taggable, 052 Commentable, 053 Identifiable, 054 LenientEquals<Installation> { 055 056 @Schema( 057 description = "Unique GBIF key for the installation.", 058 accessMode = Schema.AccessMode.READ_ONLY 059 ) 060 private UUID key; 061 062 @Schema( 063 description = "The publishing organization managing this installation.\n\n" + 064 "*(NB Not required for updates.)*" 065 ) 066 private UUID organizationKey; 067 068 @Schema( 069 description = "A shared token used to authenticate as this installation.\n" + 070 "Referred to as a shared token in user interfaces, although the API uses" + 071 "“password”." 072 ) 073 private String password; 074 075 @Schema( 076 description = "The type of the installation. Defines what protocols are used" + 077 "for communication.\n\n" + 078 "*(NB Not required for updates.)*" 079 ) 080 private InstallationType type; 081 082 @Schema( 083 description = "A name for the installation.\n\n" + 084 "*(NB Not required for updates.)*" 085 ) 086 private String title; 087 088 @Schema( 089 description = "A description for the installation." 090 ) 091 private String description; 092 093 @Schema( 094 description = "The GBIF username of the creator of the installation.", 095 accessMode = Schema.AccessMode.READ_ONLY 096 ) 097 private String createdBy; 098 099 @Schema( 100 description = "The GBIF username of the last user to modify the installation.", 101 accessMode = Schema.AccessMode.READ_ONLY 102 ) 103 private String modifiedBy; 104 105 @Schema( 106 description = "Timestamp of when the installation was created.", 107 accessMode = Schema.AccessMode.READ_ONLY 108 ) 109 private Date created; 110 111 @Schema( 112 description = "Timestamp of when the installation was modified.", 113 accessMode = Schema.AccessMode.READ_ONLY 114 ) 115 private Date modified; 116 117 @Schema( 118 description = "If present, the installation was deleted at this time. " + 119 "It is possible for it to be restored in the future.", 120 accessMode = Schema.AccessMode.READ_ONLY 121 ) 122 private Date deleted; 123 124 @Schema( 125 description = "Whether the installation is disabled. A disabled installation " + 126 "is not checked for new or deleted datasets, or metadata changes to existing" + 127 "datasets. However, data updates from existing datasets are not affected." 128 ) 129 private boolean disabled; 130 131 @Schema( 132 description = "A list of contacts associated with this installation.", 133 accessMode = Schema.AccessMode.READ_ONLY 134 ) 135 private List<Contact> contacts = new ArrayList<>(); 136 137 @Schema( 138 description = "A list of endpoints associated with this installation.", 139 accessMode = Schema.AccessMode.READ_ONLY 140 ) 141 private List<Endpoint> endpoints = new ArrayList<>(); 142 143 @Schema( 144 description = "A list of machine tags associated with this installation.", 145 accessMode = Schema.AccessMode.READ_ONLY 146 ) 147 private List<MachineTag> machineTags = new ArrayList<>(); 148 149 @Schema( 150 description = "A list of tags associated with this installation.", 151 accessMode = Schema.AccessMode.READ_ONLY 152 ) 153 private List<Tag> tags = new ArrayList<>(); 154 155 @Schema( 156 description = "A list of identifiers associated with this installation.", 157 accessMode = Schema.AccessMode.READ_ONLY 158 ) 159 private List<Identifier> identifiers = new ArrayList<>(); 160 161 @Schema( 162 description = "A list of comments associated with this installation.", 163 accessMode = Schema.AccessMode.READ_ONLY 164 ) 165 private List<Comment> comments = new ArrayList<>(); 166 167 @Null(groups = {PrePersist.class}) 168 @NotNull(groups = {PostPersist.class}) 169 @Override 170 public UUID getKey() { 171 return key; 172 } 173 174 @Override 175 public void setKey(UUID key) { 176 this.key = key; 177 } 178 179 @Override 180 public String getTitle() { 181 return title; 182 } 183 184 public boolean isDisabled() { 185 return disabled; 186 } 187 188 public void setDisabled(boolean disabled) { 189 this.disabled = disabled; 190 } 191 192 @Override 193 public void setTitle(String title) { 194 this.title = title; 195 } 196 197 @Override 198 public String getDescription() { 199 return description; 200 } 201 202 @Override 203 public void setDescription(String description) { 204 this.description = description; 205 } 206 207 @Null(groups = {PrePersist.class}) 208 @NotNull(groups = {PostPersist.class}) 209 @Override 210 public Date getCreated() { 211 return created; 212 } 213 214 @Override 215 public void setCreated(Date created) { 216 this.created = created; 217 } 218 219 @Null(groups = {PrePersist.class}) 220 @NotNull(groups = {PostPersist.class}) 221 @Override 222 public Date getModified() { 223 return modified; 224 } 225 226 @Override 227 public void setModified(Date modified) { 228 this.modified = modified; 229 } 230 231 @Override 232 public Date getDeleted() { 233 return deleted; 234 } 235 236 @Override 237 public void setDeleted(Date deleted) { 238 this.deleted = deleted; 239 } 240 241 @NotNull 242 public UUID getOrganizationKey() { 243 return organizationKey; 244 } 245 246 public void setOrganizationKey(UUID organizationKey) { 247 this.organizationKey = organizationKey; 248 } 249 250 /** 251 * Get the installation password. This method is to be ignored on serialization, so that the password is not 252 * revealed in the web service response. 253 * 254 * @return organization password 255 */ 256 @JsonIgnore 257 @Nullable 258 public String getPassword() { 259 return password; 260 } 261 262 public void setPassword(String password) { 263 this.password = password; 264 } 265 266 @NotNull 267 public InstallationType getType() { 268 return type; 269 } 270 271 public void setType(InstallationType type) { 272 this.type = type; 273 } 274 275 @Override 276 public String getCreatedBy() { 277 return createdBy; 278 } 279 280 @Override 281 public void setCreatedBy(String createdBy) { 282 this.createdBy = createdBy; 283 } 284 285 @Override 286 public String getModifiedBy() { 287 return modifiedBy; 288 } 289 290 @Override 291 public void setModifiedBy(String modifiedBy) { 292 this.modifiedBy = modifiedBy; 293 } 294 295 @Override 296 public List<Contact> getContacts() { 297 return contacts; 298 } 299 300 @Override 301 public void setContacts(List<Contact> contacts) { 302 this.contacts = contacts; 303 } 304 305 @Override 306 public List<Endpoint> getEndpoints() { 307 return endpoints; 308 } 309 310 @Override 311 public void setEndpoints(List<Endpoint> endpoints) { 312 this.endpoints = endpoints; 313 } 314 315 @Override 316 public void addEndpoint(Endpoint endpoint) { 317 endpoints.add(endpoint); 318 } 319 320 @Override 321 public List<MachineTag> getMachineTags() { 322 return machineTags; 323 } 324 325 @Override 326 public void setMachineTags(List<MachineTag> machineTags) { 327 this.machineTags = machineTags; 328 } 329 330 @Override 331 public void addMachineTag(MachineTag machineTag) { 332 machineTags.add(machineTag); 333 } 334 335 @Override 336 public List<Tag> getTags() { 337 return tags; 338 } 339 340 @Override 341 public void setTags(List<Tag> tags) { 342 this.tags = tags; 343 } 344 345 @Override 346 public List<Identifier> getIdentifiers() { 347 return identifiers; 348 } 349 350 @Override 351 public void setIdentifiers(List<Identifier> identifiers) { 352 this.identifiers = identifiers; 353 } 354 355 @Override 356 public List<Comment> getComments() { 357 return comments; 358 } 359 360 @Override 361 public void setComments(List<Comment> comments) { 362 this.comments = comments; 363 } 364 365 @Override 366 public boolean equals(Object o) { 367 if (this == o) { 368 return true; 369 } 370 if (o == null || getClass() != o.getClass()) { 371 return false; 372 } 373 Installation that = (Installation) o; 374 return disabled == that.disabled 375 && Objects.equals(key, that.key) 376 && Objects.equals(organizationKey, that.organizationKey) 377 && Objects.equals(password, that.password) 378 && type == that.type 379 && Objects.equals(title, that.title) 380 && Objects.equals(description, that.description) 381 && Objects.equals(createdBy, that.createdBy) 382 && Objects.equals(modifiedBy, that.modifiedBy) 383 && Objects.equals(created, that.created) 384 && Objects.equals(modified, that.modified) 385 && Objects.equals(deleted, that.deleted) 386 && Objects.equals(contacts, that.contacts) 387 && Objects.equals(endpoints, that.endpoints) 388 && Objects.equals(machineTags, that.machineTags) 389 && Objects.equals(tags, that.tags) 390 && Objects.equals(identifiers, that.identifiers) 391 && Objects.equals(comments, that.comments); 392 } 393 394 @Override 395 public int hashCode() { 396 return Objects.hash( 397 key, 398 organizationKey, 399 password, 400 type, 401 title, 402 description, 403 createdBy, 404 modifiedBy, 405 created, 406 modified, 407 deleted, 408 disabled, 409 contacts, 410 endpoints, 411 machineTags, 412 tags, 413 identifiers, 414 comments); 415 } 416 417 @Override 418 public String toString() { 419 return new StringJoiner(", ", Installation.class.getSimpleName() + "[", "]") 420 .add("key=" + key) 421 .add("organizationKey=" + organizationKey) 422 .add("password='" + password + "'") 423 .add("type=" + type) 424 .add("title='" + title + "'") 425 .add("description='" + description + "'") 426 .add("createdBy='" + createdBy + "'") 427 .add("modifiedBy='" + modifiedBy + "'") 428 .add("created=" + created) 429 .add("modified=" + modified) 430 .add("deleted=" + deleted) 431 .add("disabled=" + disabled) 432 .add("contacts=" + contacts) 433 .add("endpoints=" + endpoints) 434 .add("machineTags=" + machineTags) 435 .add("tags=" + tags) 436 .add("identifiers=" + identifiers) 437 .add("comments=" + comments) 438 .toString(); 439 } 440 441 /** 442 * Does not include the nested properties, or server controlled values (key, createdBy etc) or the password, 443 * for security reasons. 444 */ 445 @Override 446 public boolean lenientEquals(Installation other) { 447 if (this == other) { 448 return true; 449 } 450 return Objects.equals(this.organizationKey, other.organizationKey) 451 && Objects.equals(this.type, other.type) 452 && Objects.equals(this.title, other.title) 453 && Objects.equals(this.description, other.description); 454 } 455}