Project

General

Profile

Download (8.73 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.Comparator;
16
import java.util.HashMap;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.UUID;
20

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

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

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

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

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

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

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

    
48

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

    
52
    static {
53

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

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

    
61
    }
62

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

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

    
72
// ***********************************************************************
73

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

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

    
87

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

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

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

    
101

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

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

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

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

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

    
141
        Collections.sort(topLevelNodes, areaNodeComparator);
142

    
143
        for(AreaNode topLevelNode : topLevelNodes) {
144

    
145
            StringBuilder areaStatusString = new StringBuilder();
146

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

    
155

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

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

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

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

    
177
        return result;
178
    }
179

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

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

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

    
193
        for(AreaNode node : areaNodes) {
194

    
195
            StringBuilder subAreaString = new StringBuilder();
196

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

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

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

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

    
225
    private class AreaNodeComparator implements Comparator<AreaNode>{
226

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

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

    
244
    }
245

    
246
}
(6-6/14)