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 io.swagger.v3.oas.annotations.media.Schema;
019
020import org.gbif.api.util.IdentifierUtils;
021import org.gbif.api.vocabulary.IdentifierType;
022
023import java.io.Serializable;
024import java.util.Date;
025import java.util.Objects;
026import java.util.StringJoiner;
027
028import javax.annotation.Nullable;
029import javax.validation.constraints.Min;
030import javax.validation.constraints.NotNull;
031import javax.validation.constraints.Null;
032import javax.validation.constraints.Size;
033
034import com.fasterxml.jackson.annotation.JsonIgnore;
035
036public class Identifier implements Serializable, LenientEquals<Identifier> {
037
038  @Schema(
039    description = "Database identifier for the identifier",
040    accessMode = Schema.AccessMode.READ_ONLY
041  )
042  private Integer key;
043
044  private IdentifierType type;
045
046  @Schema(description = "Value for the identifier")
047  private String identifier;
048
049  @Schema(
050    description = "The GBIF username of the creator of the identifier",
051    accessMode = Schema.AccessMode.READ_ONLY
052  )
053  private String createdBy;
054
055  @Schema(
056    description = "Timestamp of when the identifier was created",
057    accessMode = Schema.AccessMode.READ_ONLY
058  )
059  private Date created;
060
061  @Schema(
062    description = "Whether this is the primary identifier for the associated entity."
063  )
064  @NotNull
065  private Boolean primary = false;
066
067  public Identifier() {}
068
069  public Identifier(IdentifierType type, String identifier) {
070    this.type = type;
071    this.identifier = identifier;
072  }
073
074  @Null(groups = {PrePersist.class})
075  @NotNull(groups = {PostPersist.class})
076  @Min(1)
077  public Integer getKey() {
078    return key;
079  }
080
081  public void setKey(Integer key) {
082    this.key = key;
083  }
084
085  @NotNull
086  public IdentifierType getType() {
087    return type;
088  }
089
090  public void setType(IdentifierType type) {
091    this.type = type;
092  }
093
094  @NotNull
095  @Size(min = 1)
096  public String getIdentifier() {
097    return identifier;
098  }
099
100  public void setIdentifier(String identifier) {
101    this.identifier = identifier;
102  }
103
104  @Size(min = 3)
105  public String getCreatedBy() {
106    return createdBy;
107  }
108
109  public void setCreatedBy(String createdBy) {
110    this.createdBy = createdBy;
111  }
112
113  @Null(groups = {PrePersist.class})
114  @NotNull(groups = {PostPersist.class})
115  public Date getCreated() {
116    return created;
117  }
118
119  public void setCreated(Date created) {
120    this.created = created;
121  }
122
123  public boolean isPrimary() {
124    return primary;
125  }
126
127  public void setPrimary(boolean primary) {
128    this.primary = primary;
129  }
130
131  /**
132   * Creates a http link for an identifier if possible by passing it to some known resolvers for the specific id type.
133   * If no link can be constructed, null is returned.
134   *
135   * @return the url or null if it cannot be created
136   *
137   * @see org.gbif.api.util.IdentifierUtils#getIdentifierLink(String, org.gbif.api.vocabulary.IdentifierType)
138   */
139  @Nullable
140  @JsonIgnore
141  public String getIdentifierLink() {
142    return IdentifierUtils.getIdentifierLink(identifier, type);
143  }
144
145  @Override
146  public boolean equals(Object o) {
147    if (this == o) {
148      return true;
149    }
150    if (o == null || getClass() != o.getClass()) {
151      return false;
152    }
153    Identifier that = (Identifier) o;
154    return Objects.equals(key, that.key)
155        && type == that.type
156        && Objects.equals(identifier, that.identifier)
157        && Objects.equals(createdBy, that.createdBy)
158        && Objects.equals(created, that.created)
159        && primary == that.primary;
160  }
161
162  @Override
163  public int hashCode() {
164    return Objects.hash(key, type, identifier, createdBy, created, primary);
165  }
166
167  @Override
168  public String toString() {
169    return new StringJoiner(", ", Identifier.class.getSimpleName() + "[", "]")
170        .add("key=" + key)
171        .add("type=" + type)
172        .add("identifier='" + identifier + "'")
173        .add("createdBy='" + createdBy + "'")
174        .add("created=" + created + "'")
175        .add("primary=" + primary)
176        .toString();
177  }
178
179  /**
180   * A lenient equality check ignoring server controlled values (createdBy, key etc).
181   */
182  @Override
183  public boolean lenientEquals(Identifier other) {
184    if (this == other) {
185      return true;
186    }
187    return Objects.equals(this.type, other.type)
188        && Objects.equals(this.identifier, other.identifier);
189  }
190}