001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.model.checklistbank; 015 016import org.gbif.api.vocabulary.Extension; 017import org.gbif.dwc.terms.Term; 018import org.gbif.dwc.terms.TermFactory; 019 020import java.util.Date; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.Objects; 025import java.util.StringJoiner; 026 027import javax.annotation.Nullable; 028import javax.validation.constraints.NotNull; 029 030import org.apache.commons.lang3.StringUtils; 031 032import com.fasterxml.jackson.annotation.JsonAnyGetter; 033import com.fasterxml.jackson.annotation.JsonAnySetter; 034import com.fasterxml.jackson.annotation.JsonIgnore; 035 036import io.swagger.v3.oas.annotations.media.Schema; 037 038@SuppressWarnings("unused") 039public class VerbatimNameUsage { 040 041 private Integer key; 042 // the verbatim taxon fields for the usage 043 private Map<Term, String> fields = new HashMap<>(); 044 // the verbatim extension records as read by a dwc star record, keyed on the extension 045 private Map<Extension, List<Map<Term, String>>> extensions = new HashMap<>(); 046 047 private Date lastCrawled; 048 049 /** 050 * @return The name usage key 051 */ 052 @Schema(description = "The name usage key that uniquely identifies this name usage.") 053 @NotNull 054 public Integer getKey() { 055 return key; 056 } 057 058 public void setKey(Integer key) { 059 this.key = key; 060 } 061 062 /** 063 * A map of extension records, holding all verbatim extension terms. 064 */ 065 @Schema(description = "Extension records, holding all verbatim extension terms.\n\n" + 066 "A map keyed by extension term names, containing lists of property terms + values.") 067 @NotNull 068 public Map<Extension, List<Map<Term, String>>> getExtensions() { 069 return extensions; 070 } 071 072 public void setExtensions(Map<Extension, List<Map<Term, String>>> extensions) { 073 this.extensions = extensions; 074 } 075 076 /** 077 * A map holding all verbatim core terms. 078 */ 079 @NotNull 080 @JsonIgnore 081 public Map<Term, String> getFields() { 082 return fields; 083 } 084 085 public void setFields(Map<Term, String> fields) { 086 this.fields = fields; 087 } 088 089 /** 090 * The date this record was last crawled during clb indexing. 091 */ 092 @Schema(description = "The date this record was last crawled (downloaded from the source) during Checklistbank indexing.") 093 @Nullable 094 public Date getLastCrawled() { 095 return lastCrawled == null ? null : new Date(lastCrawled.getTime()); 096 } 097 098 public void setLastCrawled(@Nullable Date lastCrawled) { 099 this.lastCrawled = lastCrawled == null ? null : new Date(lastCrawled.getTime()); 100 } 101 102 /** 103 * Get the value of a specific field (Term). 104 */ 105 @Nullable 106 public String getCoreField(Term term) { 107 Objects.requireNonNull(term, "term can't be null"); 108 return fields.get(term); 109 } 110 111 /** 112 * @return true if a verbatim field exists and is not null or an empty string 113 */ 114 public boolean hasCoreField(Term term) { 115 Objects.requireNonNull(term, "term can't be null"); 116 return StringUtils.isNotEmpty(fields.get(term)); 117 } 118 119 /** 120 * @return true if at least one extension record exists 121 */ 122 public boolean hasExtension(Extension extension) { 123 return extensions.containsKey(extension) && !extensions.get(extension).isEmpty(); 124 } 125 126 public boolean hasExtension(Term term) { 127 Objects.requireNonNull(term, "term can't be null"); 128 Extension ext = Extension.fromRowType(term.qualifiedName()); 129 130 return ext != null && hasExtension(ext); 131 } 132 133 /** 134 * For setting a specific field without having to replace the entire fields Map. 135 * 136 * @param term the field to set 137 * @param fieldValue the field's value 138 */ 139 public void setCoreField(Term term, @Nullable String fieldValue) { 140 Objects.requireNonNull(term, "term can't be null"); 141 fields.put(term, fieldValue); 142 } 143 144 /** 145 * This private method is only for deserialization via jackson and not exposed anywhere else! 146 */ 147 @JsonAnySetter 148 private void addJsonVerbatimField(String key, String value) { 149 Term t = TermFactory.instance().findTerm(key); 150 fields.put(t, value); 151 } 152 153 /** 154 * This private method is only for serialization via jackson and not exposed anywhere else! 155 * It maps the verbatimField terms into properties with their full qualified name. 156 */ 157 @JsonAnyGetter 158 private Map<String, String> jsonVerbatimFields() { 159 Map<String, String> extendedProps = new HashMap<>(); 160 for (Map.Entry<Term, String> prop : fields.entrySet()) { 161 extendedProps.put(prop.getKey().qualifiedName(), prop.getValue()); 162 } 163 return extendedProps; 164 } 165 166 @Override 167 public boolean equals(Object o) { 168 if (this == o) { 169 return true; 170 } 171 if (o == null || getClass() != o.getClass()) { 172 return false; 173 } 174 VerbatimNameUsage that = (VerbatimNameUsage) o; 175 return Objects.equals(key, that.key) && 176 Objects.equals(fields, that.fields) && 177 Objects.equals(extensions, that.extensions) && 178 Objects.equals(lastCrawled, that.lastCrawled); 179 } 180 181 @Override 182 public int hashCode() { 183 return Objects.hash(key, fields, extensions, lastCrawled); 184 } 185 186 @Override 187 public String toString() { 188 return new StringJoiner(", ", VerbatimNameUsage.class.getSimpleName() + "[", "]") 189 .add("key=" + key) 190 .add("fields=" + fields) 191 .add("extensions=" + extensions) 192 .add("lastCrawled=" + lastCrawled) 193 .toString(); 194 } 195}