Project

General

Profile

Download (8.64 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2015 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.ext.geo;
10

    
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.Collections;
14
import java.util.Comparator;
15
import java.util.HashMap;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.UUID;
19

    
20
import org.apache.commons.lang.StringUtils;
21
import org.apache.log4j.Logger;
22

    
23
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
24
import eu.etaxonomy.cdm.common.UTF8;
25
import eu.etaxonomy.cdm.model.common.Language;
26
import eu.etaxonomy.cdm.model.description.Distribution;
27
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
28
import eu.etaxonomy.cdm.model.location.NamedArea;
29

    
30
/**
31
 * @author a.mueller
32
 * @since Apr 05, 2016
33
 */
34
public class FloraCubaCondensedDistributionComposer extends CondensedDistributionComposerBase {
35

    
36
    @SuppressWarnings("unused")
37
    private static final Logger logger = Logger.getLogger(FloraCubaCondensedDistributionComposer.class);
38

    
39
//    private static Set<UUID> foreignStatusUuids;
40

    
41
    //preliminary for Cuba, needs to be parameterized
42
    private UUID uuidInternalArea = UUID.fromString("d0144a6e-0e17-4a1d-bce5-d464a2aa7229");  //Cuba
43

    
44
    private String internalAreaSeparator = UTF8.EN_DASH.toString() + " ";
45

    
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 https://dev.e-taxonomy.eu/redmine/issues/5682
54
        // ==================================================
55

    
56
       statusSymbols = new HashMap<> ();
57
       //no entries as we handle symbols now on model level
58

    
59
    }
60

    
61
// ***************************** GETTER/SETTER ***********************************/
62
    public String getInternalAreaSeparator() {
63
        return internalAreaSeparator;
64
    }
65
    public void setInternalAreaSeparator(String internalAreaSeparator) {
66
        this.internalAreaSeparator = internalAreaSeparator;
67
    }
68

    
69
// ***********************************************************************
70

    
71
    @Override
72
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
73
            List<Language> languages) {
74

    
75
        CondensedDistribution result = new CondensedDistribution();
76
//      Collection<NamedArea> allAreas = new HashSet<>();
77
        //we expect every area only to have 1 status  (multiple status should have been filtered beforehand)
78
        Map<NamedArea, PresenceAbsenceTerm> areaToStatusMap = new HashMap<>();
79

    
80

    
81
        //1. compute all areas and their status
82
        for(Distribution d : filteredDistributions) {
83
            PresenceAbsenceTerm status = d.getStatus();
84
            NamedArea area = d.getArea();
85

    
86
            //TODO needed? Do we only want to have areas with status?
87
            if(status == null || area == null) {
88
                continue;
89
            }
90

    
91
            areaToStatusMap.put(area, status);
92
        }
93

    
94

    
95
        //2. build the area hierarchy
96
        Map<NamedArea, AreaNode> areaNodeMap = new HashMap<>();
97

    
98
        for(NamedArea area : areaToStatusMap.keySet()) {
99
            AreaNode node;
100
            if(!areaNodeMap.containsKey(area)) {
101
                // putting area into hierarchy as node
102
                node = new AreaNode(area);
103
                areaNodeMap.put(area, node);
104
            } else {
105
                //  is parent of another and thus already has a node
106
                node = areaNodeMap.get(area);
107
            }
108

    
109
            NamedArea parent = findParentIn(area, areaToStatusMap.keySet());
110
            if(parent != null) {
111
                AreaNode parentNode;
112
                if(!areaNodeMap.containsKey(parent)) {
113
                    parentNode = new AreaNode(parent);
114
                    areaNodeMap.put(parent, parentNode);
115
                } else {
116
                    parentNode = areaNodeMap.get(parent);
117
                }
118
                parentNode.addSubArea(node);
119
            }
120
        }
121

    
122
        //3. find root nodes
123
        List<AreaNode>topLevelNodes = new ArrayList<>();
124
        for(AreaNode node : areaNodeMap.values()) {
125
            if(!node.hasParent() && ! topLevelNodes.contains(node)) {
126
                topLevelNodes.add(node);
127
            }
128
        }
129

    
130
        //4. replace the area by the abbreviated representation and add symbols
131
        boolean isFirstAfterAreaOfScope = false;
132
        AreaNodeComparator areaNodeComparator = new AreaNodeComparator();
133

    
134
        Collections.sort(topLevelNodes, areaNodeComparator);
135

    
136
        for(AreaNode topLevelNode : topLevelNodes) {
137

    
138
            StringBuilder areaStatusString = new StringBuilder();
139

    
140
            NamedArea area = topLevelNode.area;
141
            if (area.getUuid().equals(uuidInternalArea)){
142
                isFirstAfterAreaOfScope = true;
143
            }else if(isFirstAfterAreaOfScope && !area.getUuid().equals(uuidInternalArea)){
144
                areaStatusString.append(internalAreaSeparator);
145
                isFirstAfterAreaOfScope = false;
146
            }
147

    
148

    
149
            PresenceAbsenceTerm status = areaToStatusMap.get(area);
150
            String statusSymbol = statusSymbol(areaToStatusMap.get(area));
151
            areaStatusString.append(statusSymbol);
152

    
153
            String areaLabel = makeAreaLabel(languages, area);
154
            areaStatusString.append(areaLabel);
155

    
156
            if(!topLevelNode.subAreas.isEmpty()) {
157
                areaStatusString.append('(');
158
                subAreaLabels(languages, topLevelNode.subAreas, areaStatusString, statusSymbol,
159
                        areaLabel, areaToStatusMap, areaNodeComparator);
160
                areaStatusString.append(')');
161
            }
162

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

    
170
        return result;
171
    }
172

    
173
    /**
174
     * Recursive call to create sub area label strings
175
     * @param areaNodeComparator
176
     */
177
    private void subAreaLabels(List<Language> languages, Collection<AreaNode> nodes, StringBuilder totalStringBuilder,
178
            String parentStatusSymbol, String parentLabel,
179
            Map<NamedArea, PresenceAbsenceTerm> areaToStatusMap, AreaNodeComparator areaNodeComparator) {
180

    
181
        List<String> subAreaLabels = new ArrayList<>();
182

    
183
        List<AreaNode> areaNodes = new ArrayList<>(nodes);
184
        Collections.sort(areaNodes, areaNodeComparator);
185

    
186
        for(AreaNode node : areaNodes) {
187

    
188
            StringBuilder subAreaString = new StringBuilder();
189

    
190
            NamedArea area = node.area;
191
            PresenceAbsenceTerm status = areaToStatusMap.get(area);
192
            String subAreaStatusSymbol = statusSymbol(status);
193
            if (subAreaStatusSymbol != null && !subAreaStatusSymbol.equals(parentStatusSymbol)){
194
                subAreaString.append(subAreaStatusSymbol);
195
            }
196

    
197
            String areaLabel = makeAreaLabel(languages, area);
198
            if(replaceCommonAreaLabelStart){
199
                String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
200
                subAreaString.append(cleanSubAreaLabel);
201
            }else{
202
                subAreaString.append(areaLabel);
203
            }
204

    
205
            if(!node.subAreas.isEmpty()) {
206
                subAreaString.append('(');
207
                subAreaLabels(languages, node.subAreas, subAreaString, subAreaStatusSymbol, areaLabel,
208
                        areaToStatusMap, areaNodeComparator);
209
                subAreaString.append(')');
210
            }
211

    
212
            subAreaLabels.add(subAreaString.toString());
213
        }
214
//        Collections.sort(subAreaLabels);
215
        totalStringBuilder.append(StringUtils.join(subAreaLabels, " "));
216
    }
217

    
218
    private class AreaNodeComparator implements Comparator<AreaNode>{
219

    
220
        @Override
221
        public int compare(AreaNode areaNode1, AreaNode areaNode2) {
222
            NamedArea area1 = areaNode1.area;
223
            NamedArea area2 = areaNode2.area;
224

    
225
            if (area1 == null && area2 == null){
226
                return 0;
227
            }else if (area1 == null){
228
                return -1;
229
            }else if (area2 == null){
230
                return 1;
231
            }else{
232
                //- due to wrong ordering behavior in DefinedTerms
233
                return - area1.compareTo(area2);
234
            }
235
        }
236

    
237
    }
238

    
239
}
(6-6/14)