2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.api
.service
.dto
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import java
.util
.UUID
;
16 import org
.joda
.time
.DateTime
;
18 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
19 import eu
.etaxonomy
.cdm
.format
.taxon
.TaxonRelationshipFormatter
;
20 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
21 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
.Direction
;
22 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
23 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
24 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
25 import eu
.etaxonomy
.cdm
.model
.term
.Representation
;
26 import eu
.etaxonomy
.cdm
.persistence
.dto
.TermDto
;
27 import eu
.etaxonomy
.cdm
.strategy
.cache
.TagEnum
;
28 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedCacheHelper
;
29 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedText
;
32 * DTO to transfer a list of taxon relationships for a given taxon.
37 public class TaxonRelationshipsDTO
{
39 private static final String SENSU_SEPARATOR
= ", ";
41 public class TaxonRelationDTO
{
43 private boolean doubtful
= false;
44 private boolean misapplication
= false;
45 private boolean synonym
= false;
46 private Direction direction
;
47 private UUID taxonUuid
;
49 private List
<TaggedText
> taggedText
;
50 //TODO maybe this will be changed in future
52 private UUID typeUuid
;
53 private SourceDTO sec
;
54 private SourceDTO relSec
;
57 public TaxonRelationDTO(TaxonRelationship relation
, Direction direction
, List
<Language
> languages
) {
58 Taxon relatedTaxon
= direction
== Direction
.relatedTo? relation
.getToTaxon()
59 : relation
.getFromTaxon();
60 this.taxonUuid
= relatedTaxon
.getUuid();
61 this.doubtful
= relation
.isDoubtful();
62 this.direction
= direction
;
63 TaxonRelationshipType relType
= relation
.getType();
66 this.misapplication
= relType
.isMisappliedName();
67 this.synonym
= relType
.isAnySynonym();
68 this.typeUuid
= relType
.getUuid();
69 // TODO there must be a better DTO which also includes
70 Set
<Representation
> representations
= direction
.isDirect() ? relType
.getRepresentations() : relType
.getInverseRepresentations();
71 TermDto termDto
= TermDto
.fromTerm(relType
, representations
);
74 // termDto.localize(representation_L10n);
76 List
<TaggedText
> tags
= new TaxonRelationshipFormatter().getTaggedText(
77 relation
, direction
== Direction
.relatedFrom
, languages
);
78 this.taggedText
= tags
;
79 this.setCache(TaggedCacheHelper
.createString(tags
));
83 public UUID
getTaxonUuid() {
86 public void setTaxonUuid(UUID taxonUuid
) {
87 this.taxonUuid
= taxonUuid
;
89 public boolean isDoubtful() {
92 public void setDoubtful(boolean doubtful
) {
93 this.doubtful
= doubtful
;
96 public Direction
getDirection() {
99 public void setDirection(Direction direction
) {
100 this.direction
= direction
;
106 public String
toString(){
107 return taxonUuid
== null?
super.toString() : taxonUuid
.toString();
110 public String
getCache() {
113 public void setCache(String cache
) {
117 public List
<TaggedText
> getTaggedText() {
120 // public void setTaggedText(List<TaggedText> taggedText) {
121 // this.taggedText = taggedText;
124 public boolean isMisapplication() {
125 return misapplication
;
127 public void setMisapplication(boolean misapplication
) {
128 this.misapplication
= misapplication
;
131 public boolean isSynonym() {
134 public void setSynonym(boolean synonym
) {
135 this.synonym
= synonym
;
138 public TermDto
getType() {
141 public void setType(TermDto type
) {
147 * @return the typeUuid
149 public UUID
getTypeUuid() {
155 * @param typeUuid the typeUuid to set
157 public void setTypeUuid(UUID typeUuid
) {
158 this.typeUuid
= typeUuid
;
163 private List
<TaxonRelationDTO
> relations
= new ArrayList
<>();
165 private List
<List
<TaggedText
>> misapplications
= new ArrayList
<>();
167 private DateTime date
= DateTime
.now();
169 //** ******************* CONSTRUCTOR **************************/
171 public TaxonRelationshipsDTO() {}
173 // public TaxonRelationshipsDTO(UUID taxonUuid) {
174 // IncludedTaxon originalTaxon = new TaxonRelationshipsDTO(taxonUuid, false);
175 // includedTaxa.add(originalTaxon);
178 // ************************** GETTER / SETTER ***********************/
180 public List
<TaxonRelationDTO
> getRelations() {
184 public void setIncludedTaxa(List
<TaxonRelationDTO
> relations
) {
185 this.relations
= relations
;
188 public void addRelation(TaxonRelationDTO relation
){
189 relations
.add(relation
);
192 public TaxonRelationDTO
addRelation(TaxonRelationship relation
, Direction direction
, List
<Language
> languages
) {
193 TaxonRelationDTO newRelation
= new TaxonRelationDTO(relation
, direction
, languages
);
194 relations
.add(newRelation
);
198 public void createMisapplicationString() {
199 List
<List
<TaggedText
>> result
= new ArrayList
<>();
201 for (TaxonRelationDTO relation
: relations
){
202 if (relation
.isMisapplication()){
203 List
<TaggedText
> tags
= relation
.getTaggedText();
205 boolean isDuplicate
= false;
206 for (List
<TaggedText
> existing
: result
){
207 isDuplicate
= mergeIfDuplicate(existing
, tags
);
213 List
<TaggedText
> newTags
= new ArrayList
<>(tags
.size());
214 newTags
.addAll(tags
);
219 this.setMisapplications(result
);
223 * Checks if all tags are equal, except for the sensuReference tags
228 private boolean mergeIfDuplicate(List
<TaggedText
> first
, List
<TaggedText
> second
) {
231 int sensuEndInFirst
= -1;
232 int sensuStartInSecond
= -1;
233 int senusEndInSecond
= -1;
235 boolean sensuHandled
= false;
236 boolean isDuplicate
= true;
237 while (isDuplicate
&& i
< first
.size() && j
< second
.size()){
238 if (tagEqualsMisapplied(first
.get(i
), second
.get(i
))){
240 }else if (!sensuHandled
){
241 while (i
< first
.size() && tagIsSensu(first
.get(i
))){
245 sensuStartInSecond
= j
;
246 while (j
< second
.size() && tagIsSensu(second
.get(j
))){
248 senusEndInSecond
= j
;
253 i
++;j
++; //not really necessary
257 isDuplicate
= isDuplicate
&& i
== first
.size() && j
== second
.size();
258 if (isDuplicate
&& sensuEndInFirst
> -1 && sensuStartInSecond
> -1){
259 first
.addAll(sensuEndInFirst
, second
.subList(sensuStartInSecond
, senusEndInSecond
));
260 first
.add(sensuEndInFirst
, TaggedText
.NewSeparatorInstance(SENSU_SEPARATOR
));
267 private boolean tagIsSensu(TaggedText tag
) {
268 if (tag
.getType() == TagEnum
.secReference
||
269 tag
.getType() == TagEnum
.secMicroReference
||
270 isSensuSeparator(tag
)){
276 private boolean isSensuSeparator(TaggedText tag
) {
277 if (SENSU_SEPARATOR
.equals(tag
.getText())
278 && tag
.getType() == TagEnum
.separator
) {
284 private boolean tagEqualsMisapplied(TaggedText x
, TaggedText y
) {
285 if (CdmUtils
.nullSafeEqual(x
.getText(),y
.getText())
286 && x
.getType().equals(y
.getType())
287 && CdmUtils
.nullSafeEqual(x
.getEntityReference(),y
.getEntityReference())){
294 public DateTime
getDate() {
297 public void setDate(DateTime date
) {
301 public int getSize(){
302 return relations
.size();
305 // public boolean contains(UUID taxonUuid) {
306 // for (TaxonRelationDTO relation: relations){
307 // if (taxon.taxonUuid.equals(taxonUuid)){
315 public String
toString(){
317 for (TaxonRelationDTO relation
: relations
){
318 result
+= relation
.toString() + ",";
320 if (result
.length() > 0){
321 result
= result
.substring(0, result
.length() - 1);
324 result
= "[" + result
+ "]";
328 public List
<List
<TaggedText
>> getMisapplications() {
329 return misapplications
;
331 public void setMisapplications(List
<List
<TaggedText
>> misapplications
) {
332 this.misapplications
= misapplications
;