Project

General

Profile

Download (8.73 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
 */
35
public class FloraCubaCondensedDistributionComposer extends CondensedDistributionComposerBase {
36

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

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

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

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

    
47

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

    
51
    static {
52

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

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

    
60
    }
61

    
62
// ***************************** GETTER/SETTER ***********************************/
63
    public String getInternalAreaSeparator() {
64
        return internalAreaSeparator;
65
    }
66

    
67
    public void setInternalAreaSeparator(String internalAreaSeparator) {
68
        this.internalAreaSeparator = internalAreaSeparator;
69
    }
70

    
71
// ***********************************************************************
72

    
73
    /**
74
     * {@inheritDoc}
75
     * @return
76
     */
77
    @Override
78
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
79
            List<Language> languages) {
80

    
81
        CondensedDistribution result = new CondensedDistribution();
82
//        Collection<NamedArea> allAreas = new HashSet<NamedArea>();
83
        //we expect every area only to have 1 status  (multiple status should have been filtered beforehand)
84
        Map<NamedArea, PresenceAbsenceTerm> areaToStatusMap = new HashMap<>();
85

    
86

    
87
        //1. compute all areas and their status
88
        for(Distribution d : filteredDistributions) {
89
            PresenceAbsenceTerm status = d.getStatus();
90
            NamedArea area = d.getArea();
91

    
92
            //TODO needed? Do we only want to have areas with status?
93
            if(status == null || area == null) {
94
                continue;
95
            }
96

    
97
            areaToStatusMap.put(area, status);
98
        }
99

    
100

    
101
        //2. build the area hierarchy
102
        Map<NamedArea, AreaNode> areaNodeMap = new HashMap<>();
103

    
104
        for(NamedArea area : areaToStatusMap.keySet()) {
105
            AreaNode node;
106
            if(!areaNodeMap.containsKey(area)) {
107
                // putting area into hierarchy as node
108
                node = new AreaNode(area);
109
                areaNodeMap.put(area, node);
110
            } else {
111
                //  is parent of another and thus already has a node
112
                node = areaNodeMap.get(area);
113
            }
114

    
115
            NamedArea parent = findParentIn(area, areaToStatusMap.keySet());
116
            if(parent != null) {
117
                AreaNode parentNode;
118
                if(!areaNodeMap.containsKey(parent)) {
119
                    parentNode = new AreaNode(parent);
120
                    areaNodeMap.put(parent, parentNode);
121
                } else {
122
                    parentNode = areaNodeMap.get(parent);
123
                }
124
                parentNode.addSubArea(node);
125
            }
126
        }
127

    
128
        //3. find root nodes
129
        List<AreaNode>topLevelNodes = new ArrayList<AreaNode>();
130
        for(AreaNode node : areaNodeMap.values()) {
131
            if(!node.hasParent() && ! topLevelNodes.contains(node)) {
132
                topLevelNodes.add(node);
133
            }
134
        }
135

    
136
        //4. replace the area by the abbreviated representation and add symbols
137
        boolean isFirstAfterAreaOfScope = false;
138
        AreaNodeComparator areaNodeComparator = new AreaNodeComparator();
139

    
140
        Collections.sort(topLevelNodes, areaNodeComparator);
141

    
142
        for(AreaNode topLevelNode : topLevelNodes) {
143

    
144
            StringBuilder areaStatusString = new StringBuilder();
145

    
146
            NamedArea area = topLevelNode.area;
147
            if (area.getUuid().equals(uuidInternalArea)){
148
                isFirstAfterAreaOfScope = true;
149
            }else if(isFirstAfterAreaOfScope && !area.getUuid().equals(uuidInternalArea)){
150
                areaStatusString.append(internalAreaSeparator);
151
                isFirstAfterAreaOfScope = false;
152
            }
153

    
154

    
155
            PresenceAbsenceTerm status = areaToStatusMap.get(area);
156
            String statusSymbol = statusSymbol(areaToStatusMap.get(area));
157
            areaStatusString.append(statusSymbol);
158

    
159
            String areaLabel = makeAreaLabel(languages, area);
160
            areaStatusString.append(areaLabel);
161

    
162
            if(!topLevelNode.subAreas.isEmpty()) {
163
                areaStatusString.append('(');
164
                subAreaLabels(languages, topLevelNode.subAreas, areaStatusString, statusSymbol,
165
                        areaLabel, areaToStatusMap, areaNodeComparator);
166
                areaStatusString.append(')');
167
            }
168

    
169
//            if(isForeignStatus(status)) {
170
//                condensedDistribution.addForeignDistributionItem(status, areaStatusString.toString(), areaLabel);
171
//            } else {
172
                result.addIndigenousDistributionItem(status, areaStatusString.toString(), areaLabel);
173
//            }
174
        }
175

    
176
        return result;
177
    }
178

    
179
    /**
180
     * Recursive call to create sub area label strings
181
     * @param areaNodeComparator
182
     */
183
    private void subAreaLabels(List<Language> languages, Collection<AreaNode> nodes, StringBuilder totalStringBuilder,
184
            String parentStatusSymbol, String parentLabel,
185
            Map<NamedArea, PresenceAbsenceTerm> areaToStatusMap, AreaNodeComparator areaNodeComparator) {
186

    
187
        List<String> subAreaLabels = new ArrayList<String>();
188

    
189
        List<AreaNode> areaNodes = new ArrayList<>(nodes);
190
        Collections.sort(areaNodes, areaNodeComparator);
191

    
192
        for(AreaNode node : areaNodes) {
193

    
194
            StringBuilder subAreaString = new StringBuilder();
195

    
196
            NamedArea area = node.area;
197
            PresenceAbsenceTerm status = areaToStatusMap.get(area);
198
            String subAreaStatusSymbol = statusSymbol(status);
199
            if (subAreaStatusSymbol != null && !subAreaStatusSymbol.equals(parentStatusSymbol)){
200
                subAreaString.append(subAreaStatusSymbol);
201
            }
202

    
203
            String areaLabel = makeAreaLabel(languages, area);
204
            if(replaceCommonAreaLabelStart){
205
                String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
206
                subAreaString.append(cleanSubAreaLabel);
207
            }else{
208
                subAreaString.append(areaLabel);
209
            }
210

    
211
            if(!node.subAreas.isEmpty()) {
212
                subAreaString.append('(');
213
                subAreaLabels(languages, node.subAreas, subAreaString, subAreaStatusSymbol, areaLabel,
214
                        areaToStatusMap, areaNodeComparator);
215
                subAreaString.append(')');
216
            }
217

    
218
            subAreaLabels.add(subAreaString.toString());
219
        }
220
//        Collections.sort(subAreaLabels);
221
        totalStringBuilder.append(StringUtils.join(subAreaLabels, " "));
222
    }
223

    
224
    private class AreaNodeComparator implements Comparator<AreaNode>{
225

    
226
        @Override
227
        public int compare(AreaNode areaNode1, AreaNode areaNode2) {
228
            NamedArea area1 = areaNode1.area;
229
            NamedArea area2 = areaNode2.area;
230

    
231
            if (area1 == null && area2 == null){
232
                return 0;
233
            }else if (area1 == null){
234
                return -1;
235
            }else if (area2 == null){
236
                return 1;
237
            }else{
238
                //- due to wrong ordering behavior in DefinedTerms
239
                return - area1.compareTo(area2);
240
            }
241
        }
242

    
243
    }
244

    
245
}
(6-6/14)