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.checklistbank; 017 018import org.gbif.api.model.common.Identifier; 019import org.gbif.api.vocabulary.IdentifierType; 020import org.gbif.api.vocabulary.ThreatStatus; 021 022import java.util.ArrayList; 023import java.util.LinkedHashSet; 024import java.util.List; 025import java.util.Objects; 026import java.util.Set; 027 028import javax.validation.constraints.NotNull; 029 030import org.apache.commons.lang3.StringUtils; 031 032import com.fasterxml.jackson.annotation.JsonIgnore; 033 034/** 035 * An extension to a NameUsage adding all further properties that are not eagerly loaded. 036 * Use this class to store the various subresources as you need them side by side with the NameUsage. 037 * Note that properties are not automatically/lazy loaded in any way. 038 * This is just a simple container class with a few convenience methods which needs to be populated manually via its 039 * setters or the constructor. 040 */ 041@SuppressWarnings("unused") 042public class NameUsageContainer extends NameUsage { 043 044 private List<Description> descriptions = new ArrayList<>(); 045 private List<Distribution> distributions = new ArrayList<>(); 046 private List<Identifier> identifiers = new ArrayList<>(); 047 private List<NameUsageMediaObject> media = new ArrayList<>(); 048 private List<Reference> referenceList = new ArrayList<>(); 049 private List<SpeciesProfile> speciesProfiles = new ArrayList<>(); 050 private List<NameUsage> synonyms = new ArrayList<>(); 051 private List<NameUsage> combinations = new ArrayList<>(); 052 private List<TypeSpecimen> typeSpecimens = new ArrayList<>(); 053 private List<VernacularName> vernacularNames = new ArrayList<>(); 054 055 /** 056 * Default constructor. 057 */ 058 public NameUsageContainer() { 059 //empty constructor 060 } 061 062 /** 063 * Constructs a NameUsageContainer from an existing NameUsage instance. 064 */ 065 public NameUsageContainer(NameUsage usage) { 066 super(usage); 067 } 068 069 /** 070 * @return the list of Description 071 */ 072 @NotNull 073 public List<Description> getDescriptions() { 074 return descriptions; 075 } 076 077 /** 078 * @param descriptions the list of Description 079 */ 080 public void setDescriptions(List<Description> descriptions) { 081 this.descriptions = descriptions; 082 } 083 084 /** 085 * @return the list of Distribution 086 */ 087 @NotNull 088 public List<Distribution> getDistributions() { 089 return distributions; 090 } 091 092 /** 093 * @param distributions the Distribution list to set 094 */ 095 public void setDistributions(List<Distribution> distributions) { 096 this.distributions = distributions; 097 } 098 099 /** 100 * Convenience method that analyzes all species profile records and returns the distinct list of known habitats. 101 * 102 * @return list of unique habitats 103 */ 104 @NotNull 105 public Set<String> getHabitats() { 106 Set<String> habitats = new LinkedHashSet<>(); 107 for (SpeciesProfile sp : speciesProfiles) { 108 if (StringUtils.isNotEmpty(sp.getHabitat())) { 109 habitats.add(sp.getHabitat()); 110 } 111 } 112 return habitats; 113 } 114 115 public List<NameUsageMediaObject> getMedia() { 116 return media; 117 } 118 119 public void setMedia(List<NameUsageMediaObject> media) { 120 this.media = media; 121 } 122 123 /** 124 * @return the list of all Identifier 125 */ 126 @NotNull 127 public List<Identifier> getIdentifiers() { 128 return identifiers; 129 } 130 131 /** 132 * @param identifiers the Identifier list to set 133 */ 134 public void setIdentifiers(List<Identifier> identifiers) { 135 this.identifiers = identifiers; 136 } 137 138 /** 139 * @return the list of all URL Identifier 140 */ 141 @NotNull 142 @JsonIgnore 143 public List<Identifier> getIdentifierByType(final IdentifierType type) { 144 List<Identifier> ids = new ArrayList<>(); 145 for (Identifier i : identifiers) { 146 if (type == i.getType()) { 147 ids.add(i); 148 } 149 } 150 return ids; 151 } 152 153 /** 154 * @return the list of Reference 155 */ 156 @NotNull 157 public List<Reference> getReferenceList() { 158 return referenceList; 159 } 160 161 /** 162 * @param referenceList the Reference list to set 163 */ 164 public void setReferenceList(List<Reference> referenceList) { 165 this.referenceList = referenceList; 166 } 167 168 /** 169 * @return the list of SpeciesProfile 170 */ 171 @NotNull 172 public List<SpeciesProfile> getSpeciesProfiles() { 173 return speciesProfiles; 174 } 175 176 /** 177 * @param speciesProfiles the SpeciesProfile list to set 178 */ 179 public void setSpeciesProfiles(List<SpeciesProfile> speciesProfiles) { 180 this.speciesProfiles = speciesProfiles; 181 } 182 183 /** 184 * @return the list of synonyms 185 */ 186 public List<NameUsage> getSynonyms() { 187 return synonyms; 188 } 189 190 /** 191 * @param synonyms list of synonyms 192 */ 193 public void setSynonyms(List<NameUsage> synonyms) { 194 this.synonyms = synonyms; 195 } 196 197 /** 198 * @return the list of combinations known for the basionym 199 */ 200 @NotNull 201 public List<NameUsage> getCombinations() { 202 return combinations; 203 } 204 205 public void setCombinations(List<NameUsage> combinations) { 206 this.combinations = combinations; 207 } 208 209 /** 210 * @return the list of TypeSpecimen 211 */ 212 @NotNull 213 public List<TypeSpecimen> getTypeSpecimens() { 214 return typeSpecimens; 215 } 216 217 /** 218 * @param typeSpecimens the TypeSpecimen list to set 219 */ 220 public void setTypeSpecimens(List<TypeSpecimen> typeSpecimens) { 221 this.typeSpecimens = typeSpecimens; 222 } 223 224 /** 225 * @return the list of VernacularName 226 */ 227 @NotNull 228 public List<VernacularName> getVernacularNames() { 229 return vernacularNames; 230 } 231 232 /** 233 * @param vernacularNames the VernacularName list to set 234 */ 235 public void setVernacularNames(List<VernacularName> vernacularNames) { 236 this.vernacularNames = vernacularNames; 237 } 238 239 /** 240 * Convenience method that analyzes all species profile records and returns the distinct list of known living 241 * periods. 242 * 243 * @return list of unique living periods 244 */ 245 @NotNull 246 public Set<String> getLivingPeriods() { 247 Set<String> periods = new LinkedHashSet<>(); 248 for (SpeciesProfile sp : speciesProfiles) { 249 if (StringUtils.isNotEmpty(sp.getLivingPeriod())) { 250 periods.add(sp.getLivingPeriod()); 251 } 252 } 253 return periods; 254 } 255 256 /** 257 * Convenience method that analyzes all distribution records and returns the distinct list of known threat status. 258 * 259 * @return list of unique threat status 260 */ 261 @NotNull 262 public Set<ThreatStatus> getThreatStatus() { 263 Set<ThreatStatus> threats = new LinkedHashSet<>(); 264 for (Distribution d : distributions) { 265 if (d.getThreatStatus() != null) { 266 threats.add(d.getThreatStatus()); 267 } 268 } 269 return threats; 270 } 271 272 /** 273 * Convenience method that analyzes all species profile records for extinct. 274 * If several records contradict use the majority or if numbers are equal true. 275 * 276 * @return true if extinct 277 */ 278 public Boolean isExtinct() { 279 int ctrue = 0; 280 int cfalse = 0; 281 for (SpeciesProfile sp : speciesProfiles) { 282 if (sp.isExtinct() == null) { 283 continue; 284 } 285 286 if (sp.isExtinct()) { 287 ctrue++; 288 } else if (!sp.isExtinct()) { 289 cfalse++; 290 } 291 } 292 return ctrue + cfalse == 0 ? null : ctrue >= cfalse; 293 } 294 295 /** 296 * Convenience method that analyzes all species profile records for freshwater habitat flags. 297 * 298 * @return true if freshwater 299 */ 300 public Boolean isFreshwater() { 301 int ctrue = 0; 302 int cfalse = 0; 303 for (SpeciesProfile sp : speciesProfiles) { 304 if (sp.isFreshwater() == null) { 305 continue; 306 } 307 308 if (sp.isFreshwater()) { 309 ctrue++; 310 } else if (!sp.isFreshwater()) { 311 cfalse++; 312 } 313 } 314 return ctrue + cfalse == 0 ? null : ctrue >= cfalse; 315 } 316 317 /** 318 * Convenience method that analyzes all species profile records for marine habitat flags. 319 * 320 * @return true if marine 321 */ 322 public Boolean isMarine() { 323 int ctrue = 0; 324 int cfalse = 0; 325 for (SpeciesProfile sp : speciesProfiles) { 326 if (sp.isMarine() == null) { 327 continue; 328 } 329 330 if (sp.isMarine()) { 331 ctrue++; 332 } else if (!sp.isMarine()) { 333 cfalse++; 334 } 335 } 336 return ctrue + cfalse == 0 ? null : ctrue >= cfalse; 337 } 338 339 /** 340 * Convenience method that analyzes all species profile records for terrestrial habitat flags. 341 * 342 * @return true if terrestrial 343 */ 344 public Boolean isTerrestrial() { 345 int ctrue = 0; 346 int cfalse = 0; 347 for (SpeciesProfile sp : speciesProfiles) { 348 if (sp.isTerrestrial() == null) { 349 continue; 350 } 351 352 if (sp.isTerrestrial()) { 353 ctrue++; 354 } else if (!sp.isTerrestrial()) { 355 cfalse++; 356 } 357 } 358 return ctrue + cfalse == 0 ? null : ctrue >= cfalse; 359 } 360 361 @Override 362 public boolean equals(Object o) { 363 if (this == o) { 364 return true; 365 } 366 if (o == null || getClass() != o.getClass()) { 367 return false; 368 } 369 if (!super.equals(o)) { 370 return false; 371 } 372 NameUsageContainer that = (NameUsageContainer) o; 373 return Objects.equals(descriptions, that.descriptions) && 374 Objects.equals(distributions, that.distributions) && 375 Objects.equals(media, that.media) && 376 Objects.equals(referenceList, that.referenceList) && 377 Objects.equals(speciesProfiles, that.speciesProfiles) && 378 Objects.equals(synonyms, that.synonyms) && 379 Objects.equals(typeSpecimens, that.typeSpecimens) && 380 Objects.equals(vernacularNames, that.vernacularNames); 381 } 382 383 @Override 384 public int hashCode() { 385 return Objects 386 .hash(super.hashCode(), descriptions, distributions, media, referenceList, speciesProfiles, 387 synonyms, typeSpecimens, vernacularNames); 388 } 389 390 @Override 391 public String toString() { 392 return "NameUsageContainer{" + 393 "descriptions=" + descriptions + 394 ", distributions=" + distributions + 395 ", identifiers=" + identifiers + 396 ", media=" + media + 397 ", referenceList=" + referenceList + 398 ", speciesProfiles=" + speciesProfiles + 399 ", synonyms=" + synonyms + 400 ", combinations=" + combinations + 401 ", typeSpecimens=" + typeSpecimens + 402 ", vernacularNames=" + vernacularNames + 403 "} " + super.toString(); 404 } 405}