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
.common
.Representation
;
23 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
24 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationship
;
25 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonRelationshipType
;
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 TaxonRelation
{
43 private UUID relationUuid
;
44 private boolean doubtful
= false;
45 private boolean misapplication
= false;
46 private boolean synonym
= false;
47 private Direction direction
;
48 private UUID taxonUuid
;
50 private List
<TaggedText
> taggedText
;
51 //TODO maybe this will be changed in future
53 private UUID typeUuid
;
56 public TaxonRelation(TaxonRelationship relation
, Direction direction
, List
<Language
> languages
) {
57 Taxon relatedTaxon
= direction
== Direction
.relatedTo? relation
.getToTaxon()
58 : relation
.getFromTaxon();
59 this.taxonUuid
= relatedTaxon
.getUuid();
60 this.doubtful
= relation
.isDoubtful();
61 this.relationUuid
= relation
.getUuid();
62 this.direction
= direction
;
63 TaxonRelationshipType relType
= relation
.getType();
66 this.misapplication
= relType
.isMisappliedNameOrInvalidDesignation();
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 UUID vocUuid
= relType
.getVocabulary() != null ? relType
.getVocabulary().getUuid(): null;
72 TermDto termDto
= new TermDto(relType
.getUuid(), representations
, null, vocUuid
, relType
.getOrderIndex());
75 // termDto.localize(representation_L10n);
77 List
<TaggedText
> tags
= new TaxonRelationshipFormatter().getTaggedText(
78 relation
, direction
== Direction
.relatedFrom
, languages
);
79 this.taggedText
= tags
;
80 this.setCache(TaggedCacheHelper
.createString(tags
));
84 public UUID
getTaxonUuid() {
87 public void setTaxonUuid(UUID taxonUuid
) {
88 this.taxonUuid
= taxonUuid
;
90 public boolean isDoubtful() {
93 public void setDoubtful(boolean doubtful
) {
94 this.doubtful
= doubtful
;
96 public UUID
getRelationUuid() {
99 public void setRelationUuid(UUID relationUuid
) {
100 this.relationUuid
= relationUuid
;
103 public Direction
getDirection() {
106 public void setDirection(Direction direction
) {
107 this.direction
= direction
;
113 public String
toString(){
114 return taxonUuid
== null?
super.toString() : taxonUuid
.toString();
117 public String
getCache() {
120 public void setCache(String cache
) {
124 public List
<TaggedText
> getTaggedText() {
127 // public void setTaggedText(List<TaggedText> taggedText) {
128 // this.taggedText = taggedText;
131 public boolean isMisapplication() {
132 return misapplication
;
134 public void setMisapplication(boolean misapplication
) {
135 this.misapplication
= misapplication
;
138 public boolean isSynonym() {
141 public void setSynonym(boolean synonym
) {
142 this.synonym
= synonym
;
145 public TermDto
getType() {
148 public void setType(TermDto type
) {
154 * @return the typeUuid
156 public UUID
getTypeUuid() {
162 * @param typeUuid the typeUuid to set
164 public void setTypeUuid(UUID typeUuid
) {
165 this.typeUuid
= typeUuid
;
170 private List
<TaxonRelation
> relations
= new ArrayList
<>();
172 private List
<List
<TaggedText
>> misapplications
= new ArrayList
<>();
174 private DateTime date
= DateTime
.now();
176 //** ******************* CONSTRUCTOR **************************/
178 public TaxonRelationshipsDTO() {}
180 // public TaxonRelationshipsDTO(UUID taxonUuid) {
181 // IncludedTaxon originalTaxon = new TaxonRelationshipsDTO(taxonUuid, false);
182 // includedTaxa.add(originalTaxon);
185 // ************************** GETTER / SETTER ***********************/
187 public List
<TaxonRelation
> getRelations() {
191 public void setIncludedTaxa(List
<TaxonRelation
> relations
) {
192 this.relations
= relations
;
195 public void addRelation(TaxonRelation relation
){
196 relations
.add(relation
);
203 public TaxonRelation
addRelation(TaxonRelationship relation
, Direction direction
, List
<Language
> languages
) {
204 TaxonRelation newRelation
= new TaxonRelation(relation
, direction
, languages
);
205 relations
.add(newRelation
);
213 public void createMisapplicationString() {
214 List
<List
<TaggedText
>> result
= new ArrayList
<>();
216 for (TaxonRelation relation
: relations
){
217 if (relation
.isMisapplication()){
218 List
<TaggedText
> tags
= relation
.getTaggedText();
220 boolean isDuplicate
= false;
221 for (List
<TaggedText
> existing
: result
){
222 isDuplicate
= mergeIfDuplicate(existing
, tags
);
228 List
<TaggedText
> newTags
= new ArrayList
<>(tags
.size());
229 newTags
.addAll(tags
);
234 this.setMisapplications(result
);
238 * Checks if all tags are equal, except for the sensuReference tags
243 private boolean mergeIfDuplicate(List
<TaggedText
> first
, List
<TaggedText
> second
) {
246 int sensuEndInFirst
= -1;
247 int sensuStartInSecond
= -1;
248 int senusEndInSecond
= -1;
250 boolean sensuHandled
= false;
251 boolean isDuplicate
= true;
252 while (isDuplicate
&& i
< first
.size() && j
< second
.size()){
253 if (tagEqualsMisapplied(first
.get(i
), second
.get(i
))){
255 }else if (!sensuHandled
){
256 while (i
< first
.size() && tagIsSensu(first
.get(i
))){
260 sensuStartInSecond
= j
;
261 while (j
< second
.size() && tagIsSensu(second
.get(j
))){
263 senusEndInSecond
= j
;
268 i
++;j
++; //not really necessary
272 isDuplicate
= isDuplicate
&& i
== first
.size() && j
== second
.size();
273 if (isDuplicate
&& sensuEndInFirst
> -1 && sensuStartInSecond
> -1){
274 first
.addAll(sensuEndInFirst
, second
.subList(sensuStartInSecond
, senusEndInSecond
));
275 first
.add(sensuEndInFirst
, TaggedText
.NewSeparatorInstance(SENSU_SEPARATOR
));
286 private boolean tagIsSensu(TaggedText tag
) {
287 if (tag
.getType() == TagEnum
.secReference
||
288 tag
.getType() == TagEnum
.secMicroReference
||
289 isSensuSeparator(tag
)){
299 private boolean isSensuSeparator(TaggedText tag
) {
300 if (SENSU_SEPARATOR
.equals(tag
.getText())
301 && tag
.getType() == TagEnum
.separator
) {
312 private boolean tagEqualsMisapplied(TaggedText x
, TaggedText y
) {
313 if (CdmUtils
.nullSafeEqual(x
.getText(),y
.getText())
314 && x
.getType().equals(y
.getType())
315 && CdmUtils
.nullSafeEqual(x
.getEntityReference(),y
.getEntityReference())){
322 public DateTime
getDate() {
325 public void setDate(DateTime date
) {
329 public int getSize(){
330 return relations
.size();
333 // public boolean contains(UUID taxonUuid) {
334 // for (TaxonRelation relation: relations){
335 // if (taxon.taxonUuid.equals(taxonUuid)){
343 public String
toString(){
345 for (TaxonRelation relation
: relations
){
346 result
+= relation
.toString() + ",";
348 if (result
.length() > 0){
349 result
= result
.substring(0, result
.length() - 1);
352 result
= "[" + result
+ "]";
357 * @return the misapplications
359 public List
<List
<TaggedText
>> getMisapplications() {
360 return misapplications
;
364 * @param misapplications the misapplications to set
366 public void setMisapplications(List
<List
<TaggedText
>> misapplications
) {
367 this.misapplications
= misapplications
;