Project

General

Profile

Download (15.9 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.io.Serializable;
12
import java.math.BigDecimal;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.Comparator;
17
import java.util.HashMap;
18
import java.util.HashSet;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Set;
22
import java.util.UUID;
23
import java.util.stream.Collectors;
24

    
25
import org.apache.commons.lang3.StringUtils;
26

    
27
import eu.etaxonomy.cdm.model.description.CategoricalData;
28
import eu.etaxonomy.cdm.model.description.Character;
29
import eu.etaxonomy.cdm.model.description.DescriptionBase;
30
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
31
import eu.etaxonomy.cdm.model.description.Feature;
32
import eu.etaxonomy.cdm.model.description.QuantitativeData;
33
import eu.etaxonomy.cdm.model.description.StateData;
34
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
35
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
36
import eu.etaxonomy.cdm.persistence.dto.FeatureDto;
37
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
38
import eu.etaxonomy.cdm.persistence.dto.TermDto;
39

    
40
/**
41
 * @author pplitzner
42
 * @since 16.04.2018
43
 */
44
public abstract class RowWrapperDTO <T extends DescriptionBase> implements Serializable {
45

    
46
    private static final long serialVersionUID = -7817164423660563673L;
47

    
48
    private DescriptionBaseDto description;
49

    
50
    private TaxonNodeDto taxonNode;
51
    private Map<UUID, Set<DescriptionElementDto>> featureToElementMap;
52
    private Map<UUID, Collection<String>> featureToDisplayDataMap;
53

    
54
    public RowWrapperDTO(DescriptionBaseDto specimenDescription, TaxonNodeDto taxonNode) {
55
        this.taxonNode = taxonNode;
56
        this.featureToElementMap = new HashMap<>();
57
        this.featureToDisplayDataMap = new HashMap<>();
58
        this.description = specimenDescription;
59

    
60
        List<DescriptionElementDto> elements = specimenDescription.getElements();
61
        if (elements != null){
62
            for (DescriptionElementDto descriptionElementBase : elements) {
63
    //            if(hasData(descriptionElementBase)){
64
                UUID featureUuid = descriptionElementBase.getFeatureUuid();
65
                addToFeatureToElementMap(featureUuid, descriptionElementBase);
66

    
67
                Collection<String> displayData = generateDisplayString(descriptionElementBase);
68
                if(displayData!=null){
69
                    addDisplayStringsToMap(featureUuid, displayData);
70
                }
71

    
72
            }
73
        }
74
    }
75

    
76
    /**
77
     * @param featureUuid
78
     * @param displayData
79
     */
80
    private void addDisplayStringsToMap(UUID featureUuid, Collection<String> displayData) {
81
        if (featureToDisplayDataMap.get(featureUuid) == null){
82
            featureToDisplayDataMap.put(featureUuid, new ArrayList<>());
83
        }
84
        featureToDisplayDataMap.get(featureUuid).addAll(displayData);
85
    }
86

    
87
    public QuantitativeDataDto addQuantitativeData(FeatureDto feature){
88
        QuantitativeDataDto data = new QuantitativeDataDto(feature);
89
        description.addElement(data);
90
        removeElementForFeature(feature.getUuid());
91
        addToFeatureToElementMap(feature.getUuid(), data);
92
        return data;
93
    }
94

    
95
    /**
96
     * @param feature
97
     * @param data
98
     */
99
    private void addToFeatureToElementMap(UUID featureUuid, DescriptionElementDto data) {
100
        if (featureToElementMap.get(featureUuid) == null){
101
            featureToElementMap.put(featureUuid, new HashSet<>());
102
        }
103
        featureToElementMap.get(featureUuid).add(data);
104
    }
105

    
106
    public CategoricalDataDto addCategoricalData(FeatureDto feature){
107
        CategoricalDataDto data = new CategoricalDataDto(feature);
108
        description.addElement(data);
109
        removeElementForFeature(feature.getUuid());
110
        addToFeatureToElementMap(feature.getUuid(), data);
111
        return data;
112
    }
113

    
114
    public DescriptionBaseDto getDescription() {
115
        return description;
116
    }
117

    
118
    /**
119
     * @param description the description to set
120
     */
121
    public void setDescription(DescriptionBaseDto description) {
122
        this.description = description;
123
    }
124

    
125
    public TaxonNodeDto getTaxonNode() {
126
        return taxonNode;
127
    }
128

    
129
    public Collection<String> getDisplayDataForFeature(UUID featureUuid){
130
        return featureToDisplayDataMap.get(featureUuid);
131
    }
132

    
133
    public Set<DescriptionElementDto> getDataValueForFeature(UUID featureUuid){
134
        Set<DescriptionElementDto> descriptionElementBase = featureToElementMap.get(featureUuid);
135
        return descriptionElementBase;
136
    }
137

    
138

    
139

    
140
    private Collection<String> generateDisplayString(DescriptionElementDto descriptionElementBase){
141
        Collection<String> displayData = new ArrayList<>();
142
        if(descriptionElementBase instanceof CategoricalDataDto){
143
            CategoricalDataDto categoricalData = (CategoricalDataDto)descriptionElementBase;
144
            List<StateDataDto> states = categoricalData.getStates();
145
            Collections.sort(states, new Comparator<StateDataDto>() {
146
                @Override
147
                public int compare(StateDataDto h1, StateDataDto h2) {
148
                    if (h1.getCount() == null && h2.getCount() != null){
149
                        return -1;
150
                    } else if (h2.getCount() == null && h1.getCount() != null){
151
                        return 1;
152
                    } else if (h1.getCount() != h2.getCount()){
153
                        return -h1.getCount().compareTo(h2.getCount());
154
                    } else {
155
                        if (h1.getState() == h2.getState()){
156
                            return h1.toString().compareTo(h2.toString());
157
                        } else if (h1.getState() == null){
158
                            return -1;
159
                        } else if (h2.getState() == null){
160
                            return 1;
161
                        }else{
162
                            return h1.getState().getTitleCache().compareTo(h2.getState().getTitleCache());
163
                        }
164
                    }
165
                }
166
            });
167
            displayData = states.stream()
168
                    .map(stateData->generateStateDataString(stateData))
169
                    .collect(Collectors.toList());
170
        }
171
        if(descriptionElementBase instanceof QuantitativeDataDto){
172
            QuantitativeDataDto quantitativeData = (QuantitativeDataDto)descriptionElementBase;
173
            displayData = Collections.singleton(generateQuantitativeDataString(quantitativeData));
174
        }
175
        return displayData;
176
    }
177

    
178
    private String generateQuantitativeDataString(QuantitativeDataDto quantitativeData) {
179
        String displayData;
180
        displayData = "";
181
        BigDecimal min = quantitativeData.getSpecificStatisticalValue(StatisticalMeasure.MIN().getUuid());
182
        BigDecimal max = quantitativeData.getSpecificStatisticalValue(StatisticalMeasure.MAX().getUuid());
183
        if(min!=null||max!=null){
184
            displayData += "["+(min!=null?min.toString():"?")+"-"+(max!=null?max.toString():"?")+"] ";
185
        }
186
        displayData += quantitativeData.getValues().stream()
187
                .filter(value->value.getType().getUuid().equals(StatisticalMeasure.EXACT_VALUE().getUuid()))
188
                .map(exact->exact.getValue().toString())
189
                .collect(Collectors.joining(", "));
190
        if (quantitativeData.getMeasurementUnit() != null && StringUtils.isNotBlank(displayData)){
191
            displayData += " "+ quantitativeData.getMeasurementIdInVocabulary();
192
        }
193
        return displayData;
194
    }
195

    
196
    private String generateStateDataString(StateData stateData) {
197
        return (stateData.getState()!=null?stateData.getState().getLabel():"[no state]")
198
                +(stateData.getCount()!=null?" ("+stateData.getCount()+")":"");
199
    }
200

    
201
    private String generateStateDataString(StateDataDto stateData) {
202
        return (stateData.getState()!=null?stateData.getState().getTitleCache():"[no state]")
203
                +(stateData.getCount()!=null?" ("+stateData.getCount()+")":"");
204
    }
205

    
206
    public void setDataValueForCategoricalData(UUID featureUuid, List<TermDto> states){
207
        Set<DescriptionElementDto> descriptionElementBase = featureToElementMap.get(featureUuid);
208

    
209
        if(states.isEmpty()){
210
            removeFeature(featureUuid, descriptionElementBase);
211
            return;
212
        }
213
        CategoricalDataDto categoricalData = null;
214
        if(descriptionElementBase!=null){
215
            if (descriptionElementBase.size() == 1){
216
                DescriptionElementDto dto = descriptionElementBase.iterator().next();
217
                if (dto instanceof CategoricalDataDto){
218
                    categoricalData = (CategoricalDataDto)dto;
219
                    categoricalData.setStateDataOnly(states);
220
                }
221
            }
222

    
223
        }else{
224
            Feature feature = DefinedTermBase.getTermByClassAndUUID(Feature.class, featureUuid);
225
            if (feature == null){
226
                feature = DefinedTermBase.getTermByClassAndUUID(Character.class, featureUuid);
227
            }
228
            categoricalData = new CategoricalDataDto(FeatureDto.fromFeature(feature));
229
            categoricalData.setStateDataOnly(states);
230
        }
231
        removeElementForFeature(featureUuid);
232
        description.getElements().add(categoricalData);
233
        addToFeatureToElementMap(featureUuid, categoricalData);
234

    
235
        // update display data cache
236
        addDisplayStringsToMap(featureUuid, generateDisplayString(categoricalData));
237
//        featureToDisplayDataMap.put(featureUuid, generateDisplayString(categoricalData));
238
    }
239

    
240
    /**
241
     * @param featureUuid
242
     * @param oldElement
243
     */
244
    private void removeElementForFeature(UUID featureUuid) {
245
        DescriptionElementDto oldElement = null;
246
        for (DescriptionElementDto elementDto: description.getElements()){
247
            if (elementDto.getFeatureUuid()!= null && elementDto.getFeatureUuid().equals(featureUuid)) {
248
                oldElement = elementDto;
249
                break;
250
            }
251

    
252
        }
253
        description.getElements().remove(oldElement);
254
        featureToElementMap.remove(featureUuid);
255
        featureToDisplayDataMap.remove(featureUuid);
256
    }
257

    
258
    private void removeFeature(UUID featureUuid, Set<DescriptionElementDto> descriptionElementBases) {
259
        Set<DescriptionElementDto> elements = featureToElementMap.get(featureUuid);
260
        if (elements == null){
261
            return;
262
        }
263
        Integer i = 0;
264
        Set<Integer> indices = new  HashSet<>();
265
        for (DescriptionElementDto dto: description.getElements()){
266
            for (DescriptionElementDto descElDto: descriptionElementBases) {
267
                if (dto.getFeatureUuid() != null && dto.getFeatureUuid().equals(descElDto.getFeatureUuid())){
268
                    indices.add(i);
269
                    break;
270
                }
271
            }
272
            i++;
273
        }
274
        for (int index: indices){
275
            description.getElements().remove(index);
276
        }
277
        featureToElementMap.remove(featureUuid);
278
        featureToDisplayDataMap.remove(featureUuid);
279

    
280
    }
281

    
282
    public void setDataValueForQuantitativeData(UUID featureUuid, Map<TermDto, List<String>> textFields, TermDto unit){
283
        Set<DescriptionElementDto> descriptionElementBase = featureToElementMap.get(featureUuid);
284
        if(textFields.values().stream().allMatch(listOfStrings->listOfStrings.isEmpty())){
285
            removeFeature(featureUuid, descriptionElementBase);
286
            return;
287
        }
288
        QuantitativeDataDto quantitativeData = null;
289
        if (descriptionElementBase == null){
290
            Feature feature = DefinedTermBase.getTermByClassAndUUID(Feature.class, featureUuid);
291
            if (feature == null){
292
                feature = DefinedTermBase.getTermByClassAndUUID(Character.class, featureUuid);
293
            }
294
            quantitativeData = new QuantitativeDataDto(FeatureDto.fromFeature(feature));
295
        }
296

    
297
        if(descriptionElementBase!=null){
298
            if (descriptionElementBase.size() == 1){
299
                DescriptionElementDto dto = descriptionElementBase.iterator().next();
300
                if (dto instanceof QuantitativeDataDto){
301
                    quantitativeData = (QuantitativeDataDto)dto;
302
                }
303
            }
304

    
305

    
306
        }
307
        if (quantitativeData == null){
308
            //TODO: check whether this is possible
309
            return;
310
        }
311
        quantitativeData.getValues().clear();
312
        quantitativeData.setMeasurementUnit(unit);
313
        //add back all values from text fields
314
        Set<StatisticalMeasurementValueDto> tempValues = new HashSet<>();
315
        textFields.forEach((measure, texts)->{
316
            texts.forEach(text->{
317
                String string = text;
318
                try {
319
                    if (StringUtils.isNotBlank(string)){
320
                        BigDecimal exactValue = new BigDecimal(string);
321
//                        StatisticalMeasurementValue newValue = StatisticalMeasurementValue.NewInstance(measure, exactValue);
322
                        StatisticalMeasurementValueDto newValueDto = new StatisticalMeasurementValueDto(measure, exactValue, null);
323
//                                StatisticalMeasurementValueDto.fromStatisticalMeasurementValue(newValue);
324
                        tempValues.add(newValueDto);
325
                    }
326
                } catch (NumberFormatException e) {
327
                }
328
            });
329
        });
330

    
331
        quantitativeData.setValues(tempValues);
332
        removeElementForFeature(featureUuid);
333
        description.getElements().add(quantitativeData);
334
        addToFeatureToElementMap(featureUuid, quantitativeData);
335
        addDisplayStringsToMap(featureUuid, generateDisplayString(quantitativeData));
336
//        featureToDisplayDataMap.put(featureUuid, generateDisplayString(quantitativeData));
337
    }
338

    
339
    @Override
340
    public int hashCode() {
341
        final int prime = 31;
342
        int result = 1;
343
        result = prime * result + ((description == null) ? 0 : description.hashCode());
344
        result = prime * result + ((featureToElementMap == null) ? 0 : featureToElementMap.hashCode());
345
        result = prime * result + ((taxonNode == null) ? 0 : taxonNode.hashCode());
346
        return result;
347
    }
348

    
349
    @Override
350
    public boolean equals(Object obj) {
351
        if (this == obj) {
352
            return true;
353
        }
354
        if (obj == null) {
355
            return false;
356
        }
357
        if (getClass() != obj.getClass()) {
358
            return false;
359
        }
360
        RowWrapperDTO<?> other = (RowWrapperDTO<?>) obj;
361
        if (description == null) {
362
            if (other.description != null) {
363
                return false;
364
            }
365
        } else if (!description.equals(other.description)) {
366
            return false;
367
        }
368
        if (featureToElementMap == null) {
369
            if (other.featureToElementMap != null) {
370
                return false;
371
            }
372
        } else if (!featureToElementMap.equals(other.featureToElementMap)) {
373
            return false;
374
        }
375
        if (taxonNode == null) {
376
            if (other.taxonNode != null) {
377
                return false;
378
            }
379
        } else if (!taxonNode.equals(other.taxonNode)) {
380
            return false;
381
        }
382
        return true;
383
    }
384

    
385
    public static boolean hasData(DescriptionElementDto element){
386
        if(element instanceof CategoricalDataDto){
387
            return !((CategoricalDataDto)element).getStates().isEmpty();
388
        }
389
        else if(element instanceof QuantitativeDataDto){
390
            return !((QuantitativeDataDto)element).getValues().isEmpty();
391
        }
392
        return false;
393
    }
394

    
395
    public static boolean hasData(DescriptionElementBase element){
396
        if(element instanceof CategoricalData){
397
            return !((CategoricalData)element).getStatesOnly().isEmpty();
398
        }
399
        else if(element instanceof QuantitativeData){
400
            return !((QuantitativeData)element).getStatisticalValues().isEmpty();
401
        }
402
        return false;
403
    }
404

    
405
}
(30-30/44)