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 com.fasterxml.jackson.databind.ObjectMapper;
019
020import org.gbif.api.vocabulary.MetadataType;
021
022import java.io.Serializable;
023import java.util.Date;
024import java.util.Objects;
025import java.util.StringJoiner;
026import java.util.UUID;
027
028import jakarta.validation.constraints.Min;
029import jakarta.validation.constraints.NotNull;
030import jakarta.validation.constraints.Size;
031import jakarta.validation.constraints.AssertTrue;
032
033public class Metadata implements Serializable, LenientEquals<Metadata> {
034
035  private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
036
037  private Integer key;
038  private UUID datasetKey;
039  private MetadataType type;
040  private String content;
041  private String contentJson;
042
043  private String createdBy;
044  private String modifiedBy;
045  private Date created;
046  private Date modified;
047
048  @Min(1)
049  public Integer getKey() {
050    return key;
051  }
052
053  public void setKey(Integer key) {
054    this.key = key;
055  }
056
057  @NotNull
058  public UUID getDatasetKey() {
059    return datasetKey;
060  }
061
062  public void setDatasetKey(UUID datasetKey) {
063    this.datasetKey = datasetKey;
064  }
065
066  @NotNull
067  public MetadataType getType() {
068    return type;
069  }
070
071  public void setType(MetadataType type) {
072    this.type = type;
073  }
074
075  @NotNull
076  @Size(min = 1)
077  public String getContent() {
078    return content;
079  }
080
081  public void setContent(String content) {
082    this.content = content;
083  }
084
085  public String getContentJson() {
086    return contentJson;
087  }
088
089  public void setContentJson(String contentJson) {
090    this.contentJson = contentJson;
091  }
092
093  @AssertTrue(message = "contentJson must be valid JSON")
094  public boolean isContentJsonValid() {
095    if (contentJson == null || contentJson.trim().isEmpty()) {
096      return true;
097    }
098
099    try {
100      OBJECT_MAPPER.readTree(contentJson);
101      return true;
102    } catch (Exception e) {
103      return false;
104    }
105  }
106
107  @NotNull
108  @Size(min = 3)
109  public String getCreatedBy() {
110    return createdBy;
111  }
112
113  public void setCreatedBy(String createdBy) {
114    this.createdBy = createdBy;
115  }
116
117  @NotNull
118  @Size(min = 3)
119  public String getModifiedBy() {
120    return modifiedBy;
121  }
122
123  public void setModifiedBy(String modifiedBy) {
124    this.modifiedBy = modifiedBy;
125  }
126
127  @NotNull
128  public Date getCreated() {
129    return created;
130  }
131
132  public void setCreated(Date created) {
133    this.created = created;
134  }
135
136  @NotNull
137  public Date getModified() {
138    return modified;
139  }
140
141  public void setModified(Date modified) {
142    this.modified = modified;
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    Metadata metadata = (Metadata) o;
154    return Objects.equals(key, metadata.key)
155        && Objects.equals(datasetKey, metadata.datasetKey)
156        && type == metadata.type
157        && Objects.equals(content, metadata.content)
158        && Objects.equals(contentJson, metadata.contentJson)
159        && Objects.equals(createdBy, metadata.createdBy)
160        && Objects.equals(modifiedBy, metadata.modifiedBy)
161        && Objects.equals(created, metadata.created)
162        && Objects.equals(modified, metadata.modified);
163  }
164
165  @Override
166  public int hashCode() {
167    return Objects.hash(key, datasetKey, type, content, contentJson, createdBy, modifiedBy, created, modified);
168  }
169
170  @Override
171  public String toString() {
172    return new StringJoiner(", ", Metadata.class.getSimpleName() + "[", "]")
173        .add("key=" + key)
174        .add("datasetKey=" + datasetKey)
175        .add("type=" + type)
176        .add("content='" + content + "'")
177        .add("contentJson='" + contentJson + "'")
178        .add("createdBy='" + createdBy + "'")
179        .add("modifiedBy='" + modifiedBy + "'")
180        .add("created=" + created)
181        .add("modified=" + modified)
182        .toString();
183  }
184
185  /**
186   * Does not include the key or server controlled values (created, createdBy etc).
187   */
188  @Override
189  public boolean lenientEquals(Metadata other) {
190    if (this == other) {
191      return true;
192    }
193    if (other == null) return false;
194    return Objects.equals(this.datasetKey, other.datasetKey)
195        && Objects.equals(this.type, other.type)
196        && Objects.equals(this.content, other.content)
197        && Objects.equals(this.contentJson, other.contentJson);
198  }
199}