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}