Project

General

Profile

Download (10.6 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
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.
8
*/
9
package eu.etaxonomy.cdm.api.service.dto;
10

    
11
import java.util.ArrayList;
12
import java.util.List;
13
import java.util.Set;
14
import java.util.UUID;
15
import java.util.stream.Collectors;
16

    
17
import org.joda.time.DateTime;
18

    
19
import eu.etaxonomy.cdm.common.CdmUtils;
20
import eu.etaxonomy.cdm.format.taxon.TaxonRelationshipFormatter;
21
import eu.etaxonomy.cdm.model.common.Language;
22
import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;
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.model.term.Representation;
27
import eu.etaxonomy.cdm.persistence.dto.TermDto;
28
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
29
import eu.etaxonomy.cdm.strategy.cache.TaggedCacheHelper;
30
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
31

    
32
/**
33
 * DTO to transfer a list of taxon relationships for a given taxon.
34
 *
35
 * @author a.mueller
36
 * @since 15.08.2018
37
 */
38
public class TaxonRelationshipsDTO {
39

    
40
    private static final String SENSU_SEPARATOR = ", ";
41

    
42
    public class TaxonRelationDTO{
43

    
44
        private boolean doubtful = false;
45
        private boolean misapplication = false;
46
        private boolean synonym = false;
47
        private Direction direction;
48
        private UUID taxonUuid;
49
        private String cache;
50
        private List<TaggedText> taggedText;
51
        //TODO maybe this will be changed in future
52
        private TermDto type;
53
        private UUID typeUuid;
54
        private SourceDTO sec;
55
        private SourceDTO relSec;
56
        private Set<UUID> classificationsUUIDs;
57

    
58

    
59
        public TaxonRelationDTO(TaxonRelationship relation, Direction direction, List<Language> languages) {
60
            Taxon relatedTaxon = direction == Direction.relatedTo? relation.getToTaxon()
61
                    : relation.getFromTaxon();
62
            this.taxonUuid = relatedTaxon.getUuid();
63

    
64
            classificationsUUIDs = relatedTaxon.getTaxonNodes().stream().map(tn -> tn.getClassification().getUuid()).collect(Collectors.toSet());
65
            this.doubtful = relation.isDoubtful();
66
            this.direction = direction;
67
            TaxonRelationshipType relType = relation.getType();
68

    
69
            if (relType != null){
70
                this.misapplication = relType.isMisappliedName();
71
                this.synonym = relType.isAnySynonym();
72
                this.typeUuid = relType.getUuid();
73
//                TODO there must be a better DTO which also includes
74
                Set<Representation> representations = direction.isDirect() ? relType.getRepresentations() : relType.getInverseRepresentations();
75
                TermDto termDto = TermDto.fromTerm(relType, representations);
76
                this.type = termDto;
77
//                TODO localize
78
//                termDto.localize(representation_L10n);
79
            }
80
            List<TaggedText> tags = TaxonRelationshipFormatter.INSTANCE().getTaggedText(
81
                    relation, direction == Direction.relatedFrom, languages);
82
            this.taggedText = tags;
83
            this.setCache(TaggedCacheHelper.createString(tags));
84
        }
85

    
86

    
87
        public UUID getTaxonUuid() {
88
            return taxonUuid;
89
        }
90
        public void setTaxonUuid(UUID taxonUuid) {
91
            this.taxonUuid = taxonUuid;
92
        }
93
        public boolean isDoubtful() {
94
            return doubtful;
95
        }
96
        public void setDoubtful(boolean doubtful) {
97
            this.doubtful = doubtful;
98
        }
99

    
100
        public Direction getDirection() {
101
            return direction;
102
        }
103
        public void setDirection(Direction direction) {
104
            this.direction = direction;
105
        }
106

    
107

    
108

    
109
        @Override
110
        public String toString(){
111
            return taxonUuid == null? super.toString() : taxonUuid.toString();
112
        }
113

    
114
        public String getCache() {
115
            return cache;
116
        }
117
        public void setCache(String cache) {
118
            this.cache = cache;
119
        }
120

    
121
        public List<TaggedText> getTaggedText() {
122
            return taggedText;
123
        }
124
//        public void setTaggedText(List<TaggedText> taggedText) {
125
//            this.taggedText = taggedText;
126
//        }
127

    
128
        public boolean isMisapplication() {
129
            return misapplication;
130
        }
131
        public void setMisapplication(boolean misapplication) {
132
            this.misapplication = misapplication;
133
        }
134

    
135
        public boolean isSynonym() {
136
            return synonym;
137
        }
138
        public void setSynonym(boolean synonym) {
139
            this.synonym = synonym;
140
        }
141

    
142
        public TermDto getType() {
143
            return type;
144
        }
145
        public void setType(TermDto type) {
146
            this.type = type;
147
        }
148

    
149

    
150
        /**
151
         * @return the typeUuid
152
         */
153
        public UUID getTypeUuid() {
154
            return typeUuid;
155
        }
156

    
157

    
158
        /**
159
         * @param typeUuid the typeUuid to set
160
         */
161
        public void setTypeUuid(UUID typeUuid) {
162
            this.typeUuid = typeUuid;
163
        }
164

    
165

    
166
        public Set<UUID> getClassificationsUUIDs() {
167
            return classificationsUUIDs;
168
        }
169

    
170
    }
171

    
172
    private List<TaxonRelationDTO> relations = new ArrayList<>();
173

    
174
    private List<List<TaggedText>> misapplications = new ArrayList<>();
175

    
176
    private DateTime date = DateTime.now();
177

    
178
    //** ******************* CONSTRUCTOR **************************/
179

    
180
    public TaxonRelationshipsDTO() {}
181

    
182
//    public TaxonRelationshipsDTO(UUID taxonUuid) {
183
//        IncludedTaxon originalTaxon = new TaxonRelationshipsDTO(taxonUuid, false);
184
//        includedTaxa.add(originalTaxon);
185
//    }
186

    
187
 // ************************** GETTER / SETTER  ***********************/
188

    
189
    public List<TaxonRelationDTO> getRelations() {
190
        return relations;
191
    }
192

    
193
    public void setIncludedTaxa(List<TaxonRelationDTO> relations) {
194
        this.relations = relations;
195
    }
196

    
197
    public void addRelation(TaxonRelationDTO relation){
198
        relations.add(relation);
199
    }
200

    
201
    public TaxonRelationDTO addRelation(TaxonRelationship relation, Direction direction, List<Language> languages) {
202
        TaxonRelationDTO newRelation = new TaxonRelationDTO(relation, direction, languages);
203
        relations.add(newRelation);
204
        return newRelation;
205
    }
206

    
207
    public void createMisapplicationString() {
208
        List<List<TaggedText>> result = new ArrayList<>();
209

    
210
        for (TaxonRelationDTO relation: relations){
211
            if (relation.isMisapplication()){
212
                List<TaggedText> tags = relation.getTaggedText();
213

    
214
                boolean isDuplicate = false;
215
                for (List<TaggedText> existing: result){
216
                    isDuplicate = mergeIfDuplicate(existing, tags);
217
                    if (isDuplicate){
218
                        break;
219
                    }
220
                }
221
                if (!isDuplicate){
222
                    List<TaggedText> newTags = new ArrayList<>(tags.size());
223
                    newTags.addAll(tags);
224
                    result.add(newTags);
225
                }
226
            }
227
        }
228
        this.setMisapplications(result);
229
    }
230

    
231
    /**
232
     * Checks if all tags are equal, except for the sensuReference tags
233
     * @param existing
234
     * @param tags
235
     * @return
236
     */
237
    private boolean mergeIfDuplicate(List<TaggedText> first, List<TaggedText> second) {
238
        int i = 0;
239
        int j = 0;
240
        int sensuEndInFirst = -1;
241
        int sensuStartInSecond = -1;
242
        int senusEndInSecond = -1;
243

    
244
        boolean sensuHandled = false;
245
        boolean isDuplicate = true;
246
        while (isDuplicate && i < first.size() && j< second.size()){
247
            if (tagEqualsMisapplied(first.get(i), second.get(i))){
248
                i++;j++;
249
            }else if (!sensuHandled){
250
                while (i < first.size() && tagIsSensu(first.get(i))){
251
                    i++;
252
                    sensuEndInFirst = i;
253
                }
254
                sensuStartInSecond = j;
255
                while (j< second.size() && tagIsSensu(second.get(j))){
256
                    j++;
257
                    senusEndInSecond = j;
258
                }
259
                sensuHandled = true;
260
            }else{
261
                isDuplicate = false;
262
                i++;j++; //not really necessary
263
            }
264

    
265
        }
266
        isDuplicate = isDuplicate && i == first.size() && j == second.size();
267
        if (isDuplicate && sensuEndInFirst > -1 && sensuStartInSecond > -1){
268
            first.addAll(sensuEndInFirst, second.subList(sensuStartInSecond, senusEndInSecond));
269
            first.add(sensuEndInFirst, TaggedText.NewSeparatorInstance(SENSU_SEPARATOR));
270
            return true;
271
        }else{
272
            return false;
273
        }
274
    }
275

    
276
    private boolean tagIsSensu(TaggedText tag) {
277
        if (tag.getType() == TagEnum.secReference ||
278
                tag.getType() == TagEnum.secMicroReference ||
279
                isSensuSeparator(tag)){
280
            return true;
281
        }
282
        return false;
283
    }
284

    
285
    private boolean isSensuSeparator(TaggedText tag) {
286
        if (SENSU_SEPARATOR.equals(tag.getText())
287
                && tag.getType() == TagEnum.separator) {
288
            return true;
289
        }
290
        return false;
291
    }
292

    
293
    private boolean tagEqualsMisapplied(TaggedText x, TaggedText y) {
294
        if (CdmUtils.nullSafeEqual(x.getText(),y.getText())
295
                && x.getType().equals(y.getType())
296
                && CdmUtils.nullSafeEqual(x.getEntityReference(),y.getEntityReference())){
297
            return true;
298
        }else{
299
            return false;
300
        }
301
    }
302

    
303
    public DateTime getDate() {
304
        return date;
305
    }
306
    public void setDate(DateTime date) {
307
        this.date = date;
308
    }
309

    
310
    public int getSize(){
311
        return relations.size();
312
    }
313
//
314
//    public boolean contains(UUID taxonUuid) {
315
//        for (TaxonRelationDTO relation: relations){
316
//            if (taxon.taxonUuid.equals(taxonUuid)){
317
//                return true;
318
//            }
319
//        }
320
//        return false;
321
//    }
322

    
323
    @Override
324
    public String toString(){
325
        String result = "";
326
        for (TaxonRelationDTO relation : relations){
327
            result += relation.toString() + ",";
328
        }
329
        if (result.length() > 0){
330
            result = result.substring(0, result.length() - 1);
331
        }
332

    
333
        result = "[" + result + "]";
334
        return result;
335
    }
336

    
337
    public List<List<TaggedText>> getMisapplications() {
338
        return misapplications;
339
    }
340
    public void setMisapplications(List<List<TaggedText>> misapplications) {
341
        this.misapplications = misapplications;
342
    }
343
}
(43-43/45)