Project

General

Profile

Download (11.7 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2015 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.ext.geo;
11

    
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Set;
20
import java.util.UUID;
21

    
22
import org.apache.commons.lang.StringUtils;
23
import org.apache.log4j.Logger;
24

    
25
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
26
import eu.etaxonomy.cdm.model.common.CdmBase;
27
import eu.etaxonomy.cdm.model.common.Language;
28
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
29
import eu.etaxonomy.cdm.model.description.Distribution;
30
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
31
import eu.etaxonomy.cdm.model.location.NamedArea;
32

    
33
/**
34
 * @author a.mueller
35
 * @date Apr 05, 2016
36
 *
37
 */
38
public class FloraCubaCondensedDistributionComposer implements ICondensedDistributionComposer {
39

    
40
    @SuppressWarnings("unused")
41
    private static final Logger logger = Logger.getLogger(FloraCubaCondensedDistributionComposer.class);
42

    
43
    private static Map<UUID, String> statusSymbols;
44

    
45
    private static Set<UUID> foreignStatusUuids;
46

    
47
    // these status uuids are special for EuroPlusMed and might also be used
48
    private final static UUID REPORTED_IN_ERROR_UUID =  UUID.fromString("38604788-cf05-4607-b155-86db456f7680");
49

    
50
    static {
51

    
52
        // ==================================================
53
        // Mapping as defined in ticket http://dev.e-taxonomy.eu/trac/ticket/5682
54
        // ==================================================
55

    
56
        statusSymbols = new HashMap<UUID, String> ();
57
        // ● endemic (U+25CF BLACK CIRCLE)
58
        statusSymbols.put(PresenceAbsenceTerm.ENDEMIC_FOR_THE_RELEVANT_AREA().getUuid(), "\u25CF");
59

    
60
        // Lu native (incl. archaeophytes) TODO status archaeophytes?
61
        statusSymbols.put(PresenceAbsenceTerm.NATIVE().getUuid(), "");
62
//        statusSymbols.put(PresenceAbsenceTerm.NATIVE_FORMERLY_NATIVE().getUuid(), "");
63

    
64
        // ?Lu doubtfully present (U+3F QUESTION MARK)
65
//        statusSymbols.put(PresenceAbsenceTerm.INTRODUCED_PRESENCE_QUESTIONABLE().getUuid(), "?");
66
        statusSymbols.put(PresenceAbsenceTerm.NATIVE_PRESENCE_QUESTIONABLE().getUuid(), "?");
67
//        statusSymbols.put(PresenceAbsenceTerm.PRESENT_DOUBTFULLY().getUuid(), "?");
68

    
69
        // dLu doubtfully native
70
        statusSymbols.put(PresenceAbsenceTerm.NATIVE_DOUBTFULLY_NATIVE().getUuid(), "d");
71

    
72
        // -Lu absent but reported in error (U+2D HYPHEN-MINUS)
73
//        statusSymbols.put(PresenceAbsenceTerm.INTRODUCED_REPORTED_IN_ERROR().getUuid(), "-");
74
        statusSymbols.put(PresenceAbsenceTerm.NATIVE_REPORTED_IN_ERROR().getUuid(), "-");
75
        statusSymbols.put(REPORTED_IN_ERROR_UUID, "-");
76

    
77
        // [aLu] casual alien = introduced: adventitious (casual)
78
        statusSymbols.put(PresenceAbsenceTerm.INTRODUCED_ADVENTITIOUS().getUuid(), "a");
79

    
80
        // [cLu] cultivated
81
        statusSymbols.put(PresenceAbsenceTerm.CULTIVATED() .getUuid(), "c");
82
//        statusSymbols.put(PresenceAbsenceTerm.INTRODUCED_CULTIVATED().getUuid(), "c");
83

    
84
        // [nLu] naturalized
85
        statusSymbols.put(PresenceAbsenceTerm.NATURALISED().getUuid(), "n");
86
//        statusSymbols.put(PresenceAbsenceTerm.INTRODUCED_NATURALIZED().getUuid(), "n");
87

    
88
        statusSymbols.put(PresenceAbsenceTerm.CULTIVATED_PRESENCE_QUESTIONABLE().getUuid(), "?c");
89
        statusSymbols.put(PresenceAbsenceTerm.CULTIVATED_REPORTED_IN_ERROR().getUuid(), "-c");
90

    
91

    
92
        //Cuba specific
93
        //occasionally cultivated
94
        statusSymbols.put(UUID.fromString("936c3f9a-6099-4322-9792-0a72c6c2ce25"), "(c)");
95
        //endemic, doubtfully present
96
        statusSymbols.put(UUID.fromString("5f954f08-267a-4928-b073-12328f74c187"), "?e");
97
        //non-native and doubtfully naturalised
98
        statusSymbols.put(UUID.fromString("a1e26234-831e-4190-9fe3-011aca09ddba"), "p");
99
        //rare casual
100
        statusSymbols.put(UUID.fromString("8914ce0d-7d31-4c88-8317-985f2b3a493b"), "(a)");
101
        //?non-native and doubtfully naturalised
102
        statusSymbols.put(UUID.fromString("9e0b413b-5a68-4e5b-91f2-227b4f832466"), "?p");
103
        //?adventive (casual) alien
104
        statusSymbols.put(UUID.fromString("c42ca644-1773-4230-a2ee-328a5d4a21ab"), "?a");
105
        //endemic, reported in error
106
        statusSymbols.put(UUID.fromString("679b215d-c231-4ee2-ae12-3ffc3dd528ad"), "-e");
107
        //naturalised, reported in error
108
        statusSymbols.put(UUID.fromString("8d918a37-3add-4e1c-a233-c37dbee209aa"), "-n");
109
        //non-native and doubtfully naturalised, reported in error
110
        statusSymbols.put(UUID.fromString("b9153d90-9e31-465a-a28c-79077a8ed4c2"), "-p");
111
        //adventive alien , reported in error
112
        statusSymbols.put(UUID.fromString("9b910b7b-43e3-4260-961c-6063b11cb7dc"), "-a");
113
        //doubtfully native: reported in error
114
        statusSymbols.put(UUID.fromString("71b72e24-c2b6-44a5-bdab-39f083bf0f06"), "-d");
115

    
116

    
117
    }
118

    
119
    /**
120
     * {@inheritDoc}
121
     * @return
122
     */
123
    @Override
124
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
125
            List<Language> langs) {
126
        CondensedDistribution condensedDistribution = new CondensedDistribution();
127

    
128
        //empty
129
        if (filteredDistributions == null || filteredDistributions.isEmpty()){
130
            return condensedDistribution;
131
        }
132

    
133
        OrderedTermVocabulary<NamedArea> areaVocabulary = CdmBase.deproxy(filteredDistributions.iterator().next().getArea().getVocabulary(), OrderedTermVocabulary.class);
134

    
135
        List<NamedArea> areaList = new ArrayList<NamedArea>(areaVocabulary.getOrderedTerms());
136
        Collections.reverse(areaList);
137

    
138
        for (NamedArea area : areaList){
139

    
140
            if (area.getPartOf() != null){
141
                continue;  //subarea are handled later
142
            }
143
            StringBuilder areaStatusString = new StringBuilder();
144
            Distribution distribution = getDistribution(area, filteredDistributions);
145
            if (distribution == null){
146
                continue;
147
            }
148

    
149
            PresenceAbsenceTerm status = distribution.getStatus();
150

    
151
            String statusSymbol = statusSymbol(status);
152
            areaStatusString.append(statusSymbol);
153

    
154
            String areaLabel = makeAreaLabel(langs, area);
155
            areaStatusString.append(areaLabel);
156

    
157
            if(!area.getIncludes().isEmpty()) {
158
//                areaStatusString.append('(');
159
                subAreaLabels(langs, area.getIncludes(), areaStatusString, statusSymbol, areaLabel, filteredDistributions);
160
//                areaStatusString.append(')');
161
            }
162

    
163
//            if(isForeignStatus(status)) {
164
//                condensedDistribution.addForeignDistributionItem(status, areaStatusString.toString(), areaLabel);
165
//            } else {
166
                condensedDistribution.addIndigenousDistributionItem(status, areaStatusString.toString(), areaLabel);
167
//            }
168

    
169
        }
170

    
171
//        }
172
//        //5. order the condensedDistributions alphabetically
173
//        // FIXME
174
//        condensedDistribution.sortForeign();
175
//        condensedDistribution.sortIndigenous();
176

    
177
        return condensedDistribution;
178
    }
179

    
180
    /**
181
     * @param area
182
     * @param filteredDistributions
183
     * @return
184
     */
185
    private Distribution getDistribution(NamedArea area, Collection<Distribution> filteredDistributions) {
186
        for (Distribution dist : filteredDistributions){
187
            if (dist.getArea() != null && dist.getArea().equals(area)){
188
                return dist;
189
            }
190
        }
191
        return null;
192
    }
193

    
194
    /**
195
     * @param status
196
     * @return
197
     */
198
    private String statusSymbol(PresenceAbsenceTerm status) {
199
        if(status == null) {
200
            return "";
201
        }
202
        String symbol = statusSymbols.get(status.getUuid());
203
        if(symbol == null) {
204
            symbol = "";
205
        }
206
        return symbol;
207
    }
208

    
209
//    private boolean isForeignStatus(PresenceAbsenceTerm status) {
210
//        return foreignStatusUuids.contains(status.getUuid());
211
//    }
212

    
213
    /**
214
     * @param langs
215
     * @param node
216
     * @param areaString
217
     * @param statusSymbol
218
     */
219
    private void subAreaLabels(List<Language> langs, Collection<NamedArea> subAreas, StringBuilder areaString,
220
            String statusSymbol, String parentLabel,
221
            Collection<Distribution> filteredDistributions) {
222
        //TODO very redundant with main method
223
        List<String> subAreaLabels = new ArrayList<String>();
224

    
225
        List<NamedArea> areaList = new ArrayList<NamedArea>(subAreas);
226
        Collections.reverse(areaList);
227

    
228
        for(NamedArea area : areaList) {
229

    
230
            StringBuilder subAreaString = new StringBuilder();
231
            Distribution distribution = getDistribution(area, filteredDistributions);
232
            if (distribution == null){
233
                continue;
234
            }
235

    
236

    
237
            PresenceAbsenceTerm status = distribution.getStatus();
238
            String subAreaStatusSymbol = statusSymbol(status);
239
            if (subAreaStatusSymbol != null && !subAreaStatusSymbol.equals(statusSymbol)){
240
                subAreaString.append(subAreaStatusSymbol);
241
            }
242

    
243
            String areaLabel = makeAreaLabel(langs, area);
244
            String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
245
            subAreaString.append(cleanSubAreaLabel);
246

    
247
            if(!area.getIncludes().isEmpty()) {
248
//                subAreaString.append('(');
249
                subAreaLabels(langs, area.getIncludes(), subAreaString, subAreaStatusSymbol, areaLabel, filteredDistributions);
250
//                subAreaString.append(')');
251
            }
252

    
253
            subAreaLabels.add(subAreaString.toString());
254
        }
255

    
256
//      Collections.sort(subAreaLabels);
257
        if (!subAreaLabels.isEmpty()){
258
            areaString.append("(" + StringUtils.join(subAreaLabels, " ") + ")");
259
        }
260

    
261
    }
262

    
263
    /**
264
     * @param langs
265
     * @param area
266
     * @return
267
     */
268
    private String makeAreaLabel(List<Language> langs, NamedArea area) {
269
        return area.getIdInVocabulary() != null ? area.getIdInVocabulary() :area.getPreferredRepresentation(langs).getAbbreviatedLabel();
270
    }
271

    
272
    /**
273
     * Searches for the parent are of the area given as parameter in
274
     * the Collection of areas.
275
     *
276
     * @parent area
277
     *      The area whose parent area is to be searched
278
     * @param collection
279
     *      The areas to search in.
280
     *
281
     * @return
282
     *      Either the parent if it has been found or null.
283
     */
284
    private NamedArea findParentIn(NamedArea area, Collection<NamedArea> areas) {
285
        NamedArea parent = area.getPartOf();
286
        if(parent != null && areas.contains(parent)){
287
            return parent;
288
        }
289
        return null;
290
    }
291

    
292
    class AreaNode {
293

    
294
        private final NamedArea area;
295
        private AreaNode parent = null;
296
        private final Set<AreaNode> subAreas = new HashSet<AreaNode>();
297

    
298
        /**
299
         * @param area
300
         */
301
        public AreaNode(NamedArea area) {
302
            this.area = area;
303
        }
304

    
305
        public void addSubArea(AreaNode subArea) {
306
            subAreas.add(subArea);
307
            subArea.parent = this;
308
        }
309

    
310
        public AreaNode getParent() {
311
            return parent;
312
        }
313

    
314
        public boolean hasParent() {
315
            return getParent() != null;
316
        }
317

    
318
        public Collection<NamedArea> getSubareas() {
319
            Collection<NamedArea> areas = new HashSet<NamedArea>();
320
            for(AreaNode node : subAreas) {
321
                areas.add(node.area);
322
            }
323
            return areas;
324
        }
325
    }
326

    
327
}
(5-5/12)