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.vocabulary.TagName;
021
022import java.io.Serializable;
023import java.util.Date;
024import java.util.Objects;
025import java.util.StringJoiner;
026
027import javax.validation.constraints.NotNull;
028import javax.validation.constraints.Null;
029import javax.validation.constraints.Size;
030
031/**
032 * A tag that has a namespace, name and a value. {@code created} and {@code createdBy} are automatically set upon
033 * persisting.
034 */
035// TODO: Document the rules regarding duplicate names and values
036@SuppressWarnings("unused")
037public class MachineTag implements LenientEquals<MachineTag>, Serializable {
038
039  private static final long serialVersionUID = 3475968899219274852L;
040
041  @Schema(
042    description = "Identifier for the machine tag.",
043    accessMode = Schema.AccessMode.READ_ONLY
044  )
045  private Integer key;
046
047  @Schema(
048    description = "The namespace for the machine tag."
049  )
050  private String namespace;
051
052  @Schema(
053    description = "The name (within the namespace) of the machine tag."
054  )
055  private String name;
056
057  @Schema(
058    description = "The value of the machine tag."
059  )
060  private String value;
061
062  @Schema(
063    description = "The GBIF username of the creator of the machine tag.",
064    accessMode = Schema.AccessMode.READ_ONLY
065  )
066  private String createdBy;
067
068  @Schema(
069    description = "Timestamp of when the machine tag was created.",
070    accessMode = Schema.AccessMode.READ_ONLY
071  )
072  private Date created;
073
074  public static MachineTag newInstance(String namespace, String name, String value) {
075    return new MachineTag(namespace, name, value);
076  }
077
078  public static MachineTag newInstance(TagName tagName, String value) {
079    return new MachineTag(tagName, value);
080  }
081
082  public MachineTag() {
083    // Needed
084  }
085
086  /**
087   * This is the default constructor to create new Machine Tags which takes all user settable properties.
088   */
089  public MachineTag(String namespace, String name, String value) {
090    this.namespace = namespace;
091    this.name = name;
092    this.value = value;
093  }
094
095  /**
096   * This is the other constructor to create new Machine Tags which takes all user settable properties.
097   */
098  public MachineTag(TagName tagName, String value) {
099    this(tagName.getNamespace().getNamespace(), tagName.getName(), value);
100  }
101
102  @Null(groups = {PrePersist.class})
103  @NotNull(groups = {PostPersist.class})
104  public Integer getKey() {
105    return key;
106  }
107
108  public void setKey(Integer key) {
109    this.key = key;
110  }
111
112  @NotNull
113  @Size(min = 1, max = 255)
114  public String getNamespace() {
115    return namespace;
116  }
117
118  public void setNamespace(String namespace) {
119    this.namespace = namespace;
120  }
121
122  @NotNull
123  @Size(min = 1, max = 255)
124  public String getName() {
125    return name;
126  }
127
128  public void setName(String name) {
129    this.name = name;
130  }
131
132  @NotNull
133  @Size(min = 1, max = 700)
134  public String getValue() {
135    return value;
136  }
137
138  public void setValue(String value) {
139    this.value = value;
140  }
141
142  @Size(min = 3)
143  public String getCreatedBy() {
144    return createdBy;
145  }
146
147  public void setCreatedBy(String createdBy) {
148    this.createdBy = createdBy;
149  }
150
151  @Null(groups = {PrePersist.class})
152  @NotNull(groups = {PostPersist.class})
153  public Date getCreated() {
154    return created;
155  }
156
157  public void setCreated(Date created) {
158    this.created = created;
159  }
160
161  @Override
162  public boolean equals(Object o) {
163    if (this == o) {
164      return true;
165    }
166    if (o == null || getClass() != o.getClass()) {
167      return false;
168    }
169    MachineTag that = (MachineTag) o;
170    return Objects.equals(key, that.key)
171        && Objects.equals(namespace, that.namespace)
172        && Objects.equals(name, that.name)
173        && Objects.equals(value, that.value)
174        && Objects.equals(createdBy, that.createdBy)
175        && Objects.equals(created, that.created);
176  }
177
178  @Override
179  public int hashCode() {
180    return Objects.hash(key, namespace, name, value, createdBy, created);
181  }
182
183  @Override
184  public String toString() {
185    return new StringJoiner(", ", MachineTag.class.getSimpleName() + "[", "]")
186        .add("key=" + key)
187        .add("namespace='" + namespace + "'")
188        .add("name='" + name + "'")
189        .add("value='" + value + "'")
190        .add("createdBy='" + createdBy + "'")
191        .add("created=" + created)
192        .toString();
193  }
194
195  /**
196   * This implementation of the {@link #equals(Object)} method does only check <em>business equality</em> and disregards
197   * automatically set and maintained fields like {@code createdBy, key} and possibly others in the future.
198   */
199  @Override
200  public boolean lenientEquals(MachineTag other) {
201    if (this == other) {
202      return true;
203    }
204
205    return Objects.equals(this.namespace, other.namespace)
206        && Objects.equals(this.name, other.name)
207        && Objects.equals(this.value, other.value);
208  }
209}