Project

General

Profile

« Previous | Next » 

Revision eda85815

Added by Andreas Müller almost 8 years ago

Fix sorting problem for subareas in CubaCondensedDistribution and refactor the whole class #5682

View differences:

cdmlib-ext/src/main/java/eu/etaxonomy/cdm/ext/geo/CondensedDistributionComposerBase.java
9 9
*/
10 10
package eu.etaxonomy.cdm.ext.geo;
11 11

  
12
import java.util.Collection;
13
import java.util.HashSet;
14
import java.util.List;
12 15
import java.util.Map;
16
import java.util.Set;
13 17
import java.util.UUID;
14 18

  
15 19
import eu.etaxonomy.cdm.model.common.Language;
16 20
import eu.etaxonomy.cdm.model.common.Representation;
17 21
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
22
import eu.etaxonomy.cdm.model.location.NamedArea;
18 23

  
19 24
/**
20 25
 * Base class for Distribution Composers
......
33 38
    protected String areaPostTag = "</b>";
34 39

  
35 40

  
41
    protected boolean replaceCommonAreaLabelStart;
42

  
43
    //for future use in combined DistributionComposer
44
    private boolean sortByStatus;
45

  
46

  
47
    /**
48
     * @param langs
49
     * @param area
50
     * @return
51
     */
52
    protected String makeAreaLabel(List<Language> langs, NamedArea area) {
53
        String result = area.getIdInVocabulary() != null ? area.getIdInVocabulary() :area.getPreferredRepresentation(langs).getAbbreviatedLabel();
54
        return areaPreTag + result + areaPostTag;
55
    }
56

  
36 57

  
37 58
    /**
38 59
     * @param status
......
62 83
        return "n.a.";
63 84
    }
64 85

  
86
    /**
87
     * Searches for the parent are of the area given as parameter in
88
     * the Collection of areas.
89
     *
90
     * @parent area
91
     *      The area whose parent area is to be searched
92
     * @param collection
93
     *      The areas to search in.
94
     *
95
     * @return
96
     *      Either the parent if it has been found or null.
97
     */
98
    protected NamedArea findParentIn(NamedArea area, Collection<NamedArea> areas) {
99
        NamedArea parent = area.getPartOf();
100
        if(parent != null && areas.contains(parent)){
101
            return parent;
102
        }
103
        return null;
104
    }
105

  
106
    protected class AreaNode {
107

  
108
        protected final NamedArea area;
109
        protected AreaNode parent = null;
110
        protected final Set<AreaNode> subAreas = new HashSet<AreaNode>();
111

  
112
        /**
113
         * @param area
114
         */
115
        public AreaNode(NamedArea area) {
116
            this.area = area;
117
        }
118

  
119
        public void addSubArea(AreaNode subArea) {
120
            subAreas.add(subArea);
121
            subArea.parent = this;
122
        }
123

  
124
        public AreaNode getParent() {
125
            return parent;
126
        }
127

  
128
        public boolean hasParent() {
129
            return getParent() != null;
130
        }
131

  
132
        public Collection<NamedArea> getSubareas() {
133
            Collection<NamedArea> areas = new HashSet<NamedArea>();
134
            for(AreaNode node : subAreas) {
135
                areas.add(node.area);
136
            }
137
            return areas;
138
        }
139

  
140

  
141
        @Override
142
        public String toString() {
143
            return "AreaNode [area=" + area + "]";
144
        }
145
    }
146

  
147

  
65 148
    /**
66 149
     * @param status
67 150
     * @return
68 151
     */
152
    //Keep here only in case new version does creates problems in E+M
153
    //can be deleted if no problem occurs
69 154
    private String statusSymbolEuroMedOld(PresenceAbsenceTerm status) {
70 155
        if(status == null) {
71 156
            return "";
cdmlib-ext/src/main/java/eu/etaxonomy/cdm/ext/geo/EuroPlusMedCondensedDistributionComposer.java
111 111
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
112 112
            List<Language> langs) {
113 113

  
114
        //1. order by PresenceAbsenceTerms
115
        Map<PresenceAbsenceTerm, Collection<NamedArea>> byStatus = new HashMap<PresenceAbsenceTerm, Collection<NamedArea>>();
114
        //1. group by PresenceAbsenceTerms
115
        Map<PresenceAbsenceTerm, Collection<NamedArea>> areasByStatus = new HashMap<PresenceAbsenceTerm, Collection<NamedArea>>();
116 116
        for(Distribution d : filteredDistributions) {
117 117
            PresenceAbsenceTerm status = d.getStatus();
118 118
            if(status == null) {
119 119
                continue;
120 120
            }
121
            if(!byStatus.containsKey(status)) {
122
                byStatus.put(status, new HashSet<NamedArea>());
121
            if(!areasByStatus.containsKey(status)) {
122
                areasByStatus.put(status, new HashSet<NamedArea>());
123 123
            }
124
            byStatus.get(status).add(d.getArea());
124
            areasByStatus.get(status).add(d.getArea());
125 125
        }
126 126

  
127 127
        //2. build the area hierarchy
128
        for(PresenceAbsenceTerm status : byStatus.keySet()) {
128
        for(PresenceAbsenceTerm status : areasByStatus.keySet()) {
129 129

  
130 130
            Map<NamedArea, AreaNode> areaNodeMap = new HashMap<NamedArea, AreaNode>();
131 131

  
132
            for(NamedArea area : byStatus.get(status)) {
132
            for(NamedArea area : areasByStatus.get(status)) {
133 133
                AreaNode node;
134 134
                if(!areaNodeMap.containsKey(area)) {
135 135
                    // putting area into hierarchy as node
......
140 140
                    node = areaNodeMap.get(area);
141 141
                }
142 142

  
143
                NamedArea parent = findParentIn(area, byStatus.get(status));
143
                NamedArea parent = findParentIn(area, areasByStatus.get(status));
144 144
                if(parent != null) {
145 145
                    AreaNode parentNode;
146 146
                    if(!areaNodeMap.containsKey(parent)) {
......
162 162
            }
163 163

  
164 164
            //4. replace the area by the abbreviated representation and add symbols
165
            for(AreaNode node : hierarchy) {
165
            for(AreaNode topLevelNode : hierarchy) {
166 166

  
167 167
                StringBuilder areaStatusString = new StringBuilder();
168 168

  
169 169
                String statusSymbol = statusSymbol(status);
170 170
                areaStatusString.append(statusSymbol);
171 171

  
172
                String areaLabel = node.area.getPreferredRepresentation(langs).getAbbreviatedLabel();
172
                String areaLabel = topLevelNode.area.getPreferredRepresentation(langs).getAbbreviatedLabel();
173 173
                areaStatusString.append(areaLabel);
174 174

  
175
                if(!node.subAreas.isEmpty()) {
175
                if(!topLevelNode.subAreas.isEmpty()) {
176 176
                    areaStatusString.append('(');
177
                    subAreaLabels(langs, node.subAreas, areaStatusString, statusSymbol, areaLabel);
177
                    subAreaLabels(langs, topLevelNode.subAreas, areaStatusString, statusSymbol, areaLabel);
178 178
                    areaStatusString.append(')');
179 179
                }
180 180

  
......
216 216
            subAreaString.append(statusSymbol);
217 217

  
218 218
            String areaLabel = node.area.getPreferredRepresentation(langs).getAbbreviatedLabel();
219
            String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
220
            subAreaString.append(cleanSubAreaLabel);
219
            if (replaceCommonAreaLabelStart){
220
                String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
221
                subAreaString.append(cleanSubAreaLabel);
222
            }else{
223
                subAreaString.append(areaLabel);
224
            }
221 225

  
222 226
            if(!node.subAreas.isEmpty()) {
223 227
                subAreaString.append('(');
......
232 236

  
233 237
    }
234 238

  
235
    /**
236
     * Searches for the parent are of the area given as parameter in
237
     * the Collection of areas.
238
     *
239
     * @parent area
240
     *      The area whose parent area is to be searched
241
     * @param collection
242
     *      The areas to search in.
243
     *
244
     * @return
245
     *      Either the parent if it has been found or null.
246
     */
247
    private NamedArea findParentIn(NamedArea area, Collection<NamedArea> areas) {
248
        NamedArea parent = area.getPartOf();
249
        if(parent != null && areas.contains(parent)){
250
            return parent;
251
        }
252
        return null;
253
    }
254

  
255
    class AreaNode {
256

  
257
        private final NamedArea area;
258
        private AreaNode parent = null;
259
        private final Set<AreaNode> subAreas = new HashSet<AreaNode>();
260

  
261
        /**
262
         * @param area
263
         */
264
        public AreaNode(NamedArea area) {
265
            this.area = area;
266
        }
267 239

  
268
        public void addSubArea(AreaNode subArea) {
269
            subAreas.add(subArea);
270
            subArea.parent = this;
271
        }
272

  
273
        public AreaNode getParent() {
274
            return parent;
275
        }
276

  
277
        public boolean hasParent() {
278
            return getParent() != null;
279
        }
280

  
281
        public Collection<NamedArea> getSubareas() {
282
            Collection<NamedArea> areas = new HashSet<NamedArea>();
283
            for(AreaNode node : subAreas) {
284
                areas.add(node.area);
285
            }
286
            return areas;
287
        }
288
    }
289 240

  
290 241
}
cdmlib-ext/src/main/java/eu/etaxonomy/cdm/ext/geo/FloraCubaCondensedDistributionComposer.java
11 11

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

  
20 21
import org.apache.commons.lang.StringUtils;
......
22 23

  
23 24
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
24 25
import eu.etaxonomy.cdm.common.UTF8;
25
import eu.etaxonomy.cdm.model.common.CdmBase;
26
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
27 26
import eu.etaxonomy.cdm.model.common.Language;
28
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
29 27
import eu.etaxonomy.cdm.model.description.Distribution;
30 28
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
31 29
import eu.etaxonomy.cdm.model.location.NamedArea;
......
40 38
    @SuppressWarnings("unused")
41 39
    private static final Logger logger = Logger.getLogger(FloraCubaCondensedDistributionComposer.class);
42 40

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

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

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

  
49 48

  
50
    // these status uuids are special for EuroPlusMed and might also be used
51
    private final static UUID REPORTED_IN_ERROR_UUID =  UUID.fromString("38604788-cf05-4607-b155-86db456f7680");
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");
52 51

  
53 52
    static {
54 53

  
......
61 60

  
62 61
    }
63 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

  
64 74
    /**
65 75
     * {@inheritDoc}
66 76
     * @return
67 77
     */
68 78
    @Override
69 79
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
70
            List<Language> langs) {
80
            List<Language> languages) {
71 81

  
72
        CondensedDistribution condensedDistribution = new CondensedDistribution();
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<>();
73 86

  
74
        //empty
75
        if (filteredDistributions == null || filteredDistributions.isEmpty()){
76
            return condensedDistribution;
77
        }
78 87

  
79
        OrderedTermVocabulary<NamedArea> areaVocabulary = CdmBase.deproxy(filteredDistributions.iterator().next().getArea().getVocabulary(), OrderedTermVocabulary.class);
88
        //1. compute all areas and their status
89
        for(Distribution d : filteredDistributions) {
90
            PresenceAbsenceTerm status = d.getStatus();
91
            //TODO needed? Do we only want to have areas with status?
92
            if(status == null) {
93
                continue;
94
            }
80 95

  
81
        //deproxy and reverse order
82
        List<NamedArea> areaList = new ArrayList<NamedArea>();
83
        for (DefinedTermBase<NamedArea> dtb : areaVocabulary.getOrderedTerms()){
84
            areaList.add(0, (NamedArea)CdmBase.deproxy(dtb));
96
            NamedArea area = d.getArea();
97
            areaToStatusMap.put(area, status);
85 98
        }
86 99

  
87 100

  
88
        boolean isFirstAfterInternalArea = false;
89
        for (NamedArea area : areaList){
101
        //2. build the area hierarchy
102
        Map<NamedArea, AreaNode> areaNodeMap = new HashMap<>();
90 103

  
91
            if (area.getPartOf() != null){
92
                continue;  //subarea are handled later
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);
93 113
            }
94 114

  
95
            StringBuilder areaStatusString = new StringBuilder();
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
        }
96 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
        }
97 135

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

  
99
            Distribution distribution = getDistribution(area, filteredDistributions);
100
            if (distribution == null){
101
                continue;
102
            }
140
        Collections.sort(topLevelNodes, areaNodeComparator);
103 141

  
142
        for(AreaNode topLevelNode : topLevelNodes) {
143

  
144
            StringBuilder areaStatusString = new StringBuilder();
145

  
146
            NamedArea area = topLevelNode.area;
104 147
            if (area.getUuid().equals(uuidInternalArea)){
105
                isFirstAfterInternalArea = true;
106
            }else if(isFirstAfterInternalArea && !area.getUuid().equals(uuidInternalArea)){
148
                isFirstAfterAreaOfScope = true;
149
            }else if(isFirstAfterAreaOfScope && !area.getUuid().equals(uuidInternalArea)){
107 150
                areaStatusString.append(internalAreaSeparator);
108
                isFirstAfterInternalArea = false;
151
                isFirstAfterAreaOfScope = false;
109 152
            }
110 153

  
111
            PresenceAbsenceTerm status = distribution.getStatus();
112 154

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

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

  
119
            if(!area.getIncludes().isEmpty()) {
120
//                areaStatusString.append('(');
121
                subAreaLabels(langs, area.getIncludes(), areaStatusString, statusSymbol, areaLabel, filteredDistributions);
122
//                areaStatusString.append(')');
162
            if(!topLevelNode.subAreas.isEmpty()) {
163
                areaStatusString.append('(');
164
                subAreaLabels(languages, topLevelNode.subAreas, areaStatusString, statusSymbol,
165
                        areaLabel, areaToStatusMap, areaNodeComparator);
166
                areaStatusString.append(')');
123 167
            }
124 168

  
125

  
126 169
//            if(isForeignStatus(status)) {
127 170
//                condensedDistribution.addForeignDistributionItem(status, areaStatusString.toString(), areaLabel);
128 171
//            } else {
129
                condensedDistribution.addIndigenousDistributionItem(status, areaStatusString.toString(), areaLabel);
172
                result.addIndigenousDistributionItem(status, areaStatusString.toString(), areaLabel);
130 173
//            }
131

  
132 174
        }
133 175

  
134
//        }
135
//        //5. order the condensedDistributions alphabetically
136
//        // FIXME
137
//        condensedDistribution.sortForeign();
138
//        condensedDistribution.sortIndigenous();
139

  
140
        return condensedDistribution;
176
        return result;
141 177
    }
142 178

  
143 179
    /**
144
     * @param area
145
     * @param filteredDistributions
146
     * @return
180
     * Recursive call to create sub area label strings
181
     * @param areaNodeComparator
147 182
     */
148
    private Distribution getDistribution(NamedArea area, Collection<Distribution> filteredDistributions) {
149
        for (Distribution dist : filteredDistributions){
150
            if (dist.getArea() != null && dist.getArea().equals(area)){
151
                return dist;
152
            }
153
        }
154
        return null;
155
    }
183
    private void subAreaLabels(List<Language> languages, Collection<AreaNode> nodes, StringBuilder totalStringBuilder,
184
            String parentStatusSymbol, String parentLabel,
185
            Map<NamedArea, PresenceAbsenceTerm> areaToStatusMap, AreaNodeComparator areaNodeComparator) {
156 186

  
157

  
158
//    private boolean isForeignStatus(PresenceAbsenceTerm status) {
159
//        return foreignStatusUuids.contains(status.getUuid());
160
//    }
161

  
162
    /**
163
     * @param langs
164
     * @param node
165
     * @param areaString
166
     * @param statusSymbol
167
     */
168
    private void subAreaLabels(List<Language> langs, Collection<NamedArea> subAreas, StringBuilder areaString,
169
            String statusSymbol, String parentLabel,
170
            Collection<Distribution> filteredDistributions) {
171
        //TODO very redundant with main method
172 187
        List<String> subAreaLabels = new ArrayList<String>();
173 188

  
174
        //deproxy and reverse order
175
        List<NamedArea> areaList = new ArrayList<NamedArea>();
176
        for (DefinedTermBase<NamedArea> dtb : subAreas){
177
            areaList.add(0, (NamedArea)CdmBase.deproxy(dtb));
178
        }
189
        List<AreaNode> areaNodes = new ArrayList<>(nodes);
190
        Collections.sort(areaNodes, areaNodeComparator);
179 191

  
180
        for(NamedArea area : areaList) {
192
        for(AreaNode node : areaNodes) {
181 193

  
182 194
            StringBuilder subAreaString = new StringBuilder();
183
            Distribution distribution = getDistribution(area, filteredDistributions);
184
            if (distribution == null){
185
                continue;
186
            }
187 195

  
188

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

  
195
            String areaLabel = makeAreaLabel(langs, area);
196
//            String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
197
            String cleanSubAreaLabel = areaLabel;
198
            subAreaString.append(cleanSubAreaLabel);
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
            }
199 210

  
200
            if(!area.getIncludes().isEmpty()) {
201
//                subAreaString.append('(');
202
                subAreaLabels(langs, area.getIncludes(), subAreaString, subAreaStatusSymbol, areaLabel, filteredDistributions);
203
//                subAreaString.append(')');
211
            if(!node.subAreas.isEmpty()) {
212
                subAreaString.append('(');
213
                subAreaLabels(languages, node.subAreas, subAreaString, subAreaStatusSymbol, areaLabel,
214
                        areaToStatusMap, areaNodeComparator);
215
                subAreaString.append(')');
204 216
            }
205 217

  
206 218
            subAreaLabels.add(subAreaString.toString());
207 219
        }
208

  
209
//      Collections.sort(subAreaLabels);
210
        if (!subAreaLabels.isEmpty()){
211
            areaString.append("(" + StringUtils.join(subAreaLabels, " ") + ")");
212
        }
213

  
214
    }
215

  
216
    /**
217
     * @param langs
218
     * @param area
219
     * @return
220
     */
221
    private String makeAreaLabel(List<Language> langs, NamedArea area) {
222
        String result = area.getIdInVocabulary() != null ? area.getIdInVocabulary() :area.getPreferredRepresentation(langs).getAbbreviatedLabel();
223
        return areaPreTag + result + areaPostTag;
220
//        Collections.sort(subAreaLabels);
221
        totalStringBuilder.append(StringUtils.join(subAreaLabels, " "));
224 222
    }
225 223

  
226

  
227

  
228
    public String getInternalAreaSeparator() {
229
        return internalAreaSeparator;
230
    }
231

  
232
    public void setInternalAreaSeparator(String internalAreaSeparator) {
233
        this.internalAreaSeparator = internalAreaSeparator;
234
    }
235

  
236
    /**
237
     * Searches for the parent are of the area given as parameter in
238
     * the Collection of areas.
239
     *
240
     * @parent area
241
     *      The area whose parent area is to be searched
242
     * @param collection
243
     *      The areas to search in.
244
     *
245
     * @return
246
     *      Either the parent if it has been found or null.
247
     */
248
    private NamedArea findParentIn(NamedArea area, Collection<NamedArea> areas) {
249
        NamedArea parent = area.getPartOf();
250
        if(parent != null && areas.contains(parent)){
251
            return parent;
252
        }
253
        return null;
254
    }
255

  
256
    class AreaNode {
257

  
258
        private final NamedArea area;
259
        private AreaNode parent = null;
260
        private final Set<AreaNode> subAreas = new HashSet<AreaNode>();
261

  
262
        /**
263
         * @param area
264
         */
265
        public AreaNode(NamedArea area) {
266
            this.area = area;
267
        }
268

  
269
        public void addSubArea(AreaNode subArea) {
270
            subAreas.add(subArea);
271
            subArea.parent = this;
272
        }
273

  
274
        public AreaNode getParent() {
275
            return parent;
276
        }
277

  
278
        public boolean hasParent() {
279
            return getParent() != null;
280
        }
281

  
282
        public Collection<NamedArea> getSubareas() {
283
            Collection<NamedArea> areas = new HashSet<NamedArea>();
284
            for(AreaNode node : subAreas) {
285
                areas.add(node.area);
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);
286 240
            }
287
            return areas;
288 241
        }
289
    }
290

  
291 242

  
243
    }
292 244

  
293 245
}
cdmlib-ext/src/main/java/eu/etaxonomy/cdm/ext/geo/FloraCubaCondensedDistributionComposerOld.java
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.HashMap;
15
import java.util.List;
16
import java.util.UUID;
17

  
18
import org.apache.commons.lang.StringUtils;
19
import org.apache.log4j.Logger;
20

  
21
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
22
import eu.etaxonomy.cdm.common.UTF8;
23
import eu.etaxonomy.cdm.model.common.CdmBase;
24
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
25
import eu.etaxonomy.cdm.model.common.Language;
26
import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
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 FloraCubaCondensedDistributionComposerOld extends CondensedDistributionComposerBase {
37

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

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

  
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
    /**
63
     * {@inheritDoc}
64
     * @return
65
     */
66
    @Override
67
    public CondensedDistribution createCondensedDistribution(Collection<Distribution> filteredDistributions,
68
            List<Language> languages) {
69

  
70
        CondensedDistribution condensedDistribution = new CondensedDistribution();
71

  
72
        //empty
73
        if (filteredDistributions == null || filteredDistributions.isEmpty()){
74
            return condensedDistribution;
75
        }
76

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

  
79
        //deproxy and reverse order
80
        List<NamedArea> areaList = new ArrayList<NamedArea>();
81
        for (DefinedTermBase<NamedArea> dtb : areaVocabulary.getOrderedTerms()){
82
            areaList.add(0, (NamedArea)CdmBase.deproxy(dtb));
83
        }
84

  
85

  
86
        boolean isFirstAfterInternalArea = false;
87
        for (NamedArea area : areaList){
88

  
89
            if (area.getPartOf() != null){
90
                continue;  //subarea are handled later
91
            }
92

  
93
            StringBuilder areaStatusString = new StringBuilder();
94

  
95

  
96

  
97
            Distribution distribution = getDistribution(area, filteredDistributions);
98
            if (distribution == null){
99
                continue;
100
            }
101

  
102
            if (area.getUuid().equals(uuidInternalArea)){
103
                isFirstAfterInternalArea = true;
104
            }else if(isFirstAfterInternalArea && !area.getUuid().equals(uuidInternalArea)){
105
                areaStatusString.append(internalAreaSeparator);
106
                isFirstAfterInternalArea = false;
107
            }
108

  
109
            PresenceAbsenceTerm status = distribution.getStatus();
110

  
111
            String statusSymbol = statusSymbol(status);
112
            areaStatusString.append(statusSymbol);
113

  
114
            String areaLabel = makeAreaLabel(languages, area);
115
            areaStatusString.append(areaLabel);
116

  
117
            if(!area.getIncludes().isEmpty()) {
118
//                areaStatusString.append('(');
119
                subAreaLabels(languages, area.getIncludes(), areaStatusString, statusSymbol, areaLabel, filteredDistributions);
120
//                areaStatusString.append(')');
121
            }
122

  
123

  
124
//            if(isForeignStatus(status)) {
125
//                condensedDistribution.addForeignDistributionItem(status, areaStatusString.toString(), areaLabel);
126
//            } else {
127
                condensedDistribution.addIndigenousDistributionItem(status, areaStatusString.toString(), areaLabel);
128
//            }
129

  
130
        }
131

  
132
//        }
133
//        //5. order the condensedDistributions alphabetically
134
//        // FIXME
135
//        condensedDistribution.sortForeign();
136
//        condensedDistribution.sortIndigenous();
137

  
138
        return condensedDistribution;
139
    }
140

  
141
    /**
142
     * @param area
143
     * @param filteredDistributions
144
     * @return
145
     */
146
    private Distribution getDistribution(NamedArea area, Collection<Distribution> filteredDistributions) {
147
        for (Distribution dist : filteredDistributions){
148
            if (dist.getArea() != null && dist.getArea().equals(area)){
149
                return dist;
150
            }
151
        }
152
        return null;
153
    }
154

  
155

  
156
//    private boolean isForeignStatus(PresenceAbsenceTerm status) {
157
//        return foreignStatusUuids.contains(status.getUuid());
158
//    }
159

  
160
    /**
161
     * @param langs
162
     * @param node
163
     * @param areaString
164
     * @param statusSymbol
165
     */
166
    private void subAreaLabels(List<Language> langs, Collection<NamedArea> subAreas, StringBuilder areaString,
167
            String statusSymbol, String parentLabel,
168
            Collection<Distribution> filteredDistributions) {
169
        //TODO very redundant with main method
170
        List<String> subAreaLabels = new ArrayList<String>();
171

  
172
        //deproxy and reverse order
173
        List<NamedArea> areaList = new ArrayList<NamedArea>();
174
        for (DefinedTermBase<NamedArea> dtb : subAreas){
175
            areaList.add(0, (NamedArea)CdmBase.deproxy(dtb));
176
        }
177
//        Collections.sort(areaList);
178

  
179
        for(NamedArea area : areaList) {
180

  
181
            StringBuilder subAreaString = new StringBuilder();
182
            Distribution distribution = getDistribution(area, filteredDistributions);
183
            if (distribution == null){
184
                continue;
185
            }
186

  
187

  
188
            PresenceAbsenceTerm status = distribution.getStatus();
189
            String subAreaStatusSymbol = statusSymbol(status);
190
            if (subAreaStatusSymbol != null && !subAreaStatusSymbol.equals(statusSymbol)){
191
                subAreaString.append(subAreaStatusSymbol);
192
            }
193

  
194
            String areaLabel = makeAreaLabel(langs, area);
195
//            String cleanSubAreaLabel = StringUtils.replaceEach(areaLabel, new String[] {parentLabel, "(", ")"}, new String[] {"", "", ""});
196
            String cleanSubAreaLabel = areaLabel;
197
            subAreaString.append(cleanSubAreaLabel);
198

  
199
            if(!area.getIncludes().isEmpty()) {
200
//                subAreaString.append('(');
201
                subAreaLabels(langs, area.getIncludes(), subAreaString, subAreaStatusSymbol, areaLabel, filteredDistributions);
202
//                subAreaString.append(')');
203
            }
204

  
205
            subAreaLabels.add(subAreaString.toString());
206
        }
207

  
208
//      Collections.sort(subAreaLabels);
209
        if (!subAreaLabels.isEmpty()){
210
            areaString.append("(" + StringUtils.join(subAreaLabels, " ") + ")");
211
        }
212

  
213
    }
214

  
215

  
216
    public String getInternalAreaSeparator() {
217
        return internalAreaSeparator;
218
    }
219

  
220
    public void setInternalAreaSeparator(String internalAreaSeparator) {
221
        this.internalAreaSeparator = internalAreaSeparator;
222
    }
223

  
224

  
225

  
226

  
227

  
228

  
229
}
cdmlib-ext/src/test/java/eu/etaxonomy/cdm/ext/geo/FloraCubaCondensedDistributionComposerTest.java
28 28
import eu.etaxonomy.cdm.model.location.NamedArea;
29 29

  
30 30
/**
31
 * Tests for {@link FloraCubaCondensedDistributionComposer}
31
 * Tests for {@link FloraCubaCondensedDistributionComposerOld}
32 32
 * @author a.mueller
33 33
 * @date 07.04.2016
34 34
 *
......
125 125
// ********************* TESTS ******************************/
126 126

  
127 127
    /**
128
     * Test method for {@link eu.etaxonomy.cdm.ext.geo.FloraCubaCondensedDistributionComposer#createCondensedDistribution(java.util.Collection, java.util.List)}.
128
     * Test method for {@link eu.etaxonomy.cdm.ext.geo.FloraCubaCondensedDistributionComposerOld#createCondensedDistribution(java.util.Collection, java.util.List)}.
129 129
     */
130 130
    @Test
131 131
    public void testCreateCondensedDistribution() {
132 132
        FloraCubaCondensedDistributionComposer composer = new FloraCubaCondensedDistributionComposer();
133
        composer.setAreaPreTag("");
134
        composer.setAreaPostTag("");
133
        composer.setAreaPreTag("<b>");
134
        composer.setAreaPostTag("</b>");
135 135

  
136 136
        Set<Distribution> filteredDistributions = new HashSet<Distribution>();
137 137
        filteredDistributions.add(Distribution.NewInstance(cuba, PresenceAbsenceTerm.NATURALISED()));
138 138
        filteredDistributions.add(Distribution.NewInstance(eastCuba, statusVoc.findTermByUuid(uuidStatusOccasionallyCultivated)));
139
        filteredDistributions.add(Distribution.NewInstance(westernCuba, statusVoc.findTermByUuid(uuidStatusDoubtfullyNativeError)));
139 140
        filteredDistributions.add(Distribution.NewInstance(pinarDelRio, PresenceAbsenceTerm.CULTIVATED_REPORTED_IN_ERROR()));
140 141
        filteredDistributions.add(Distribution.NewInstance(holguin, PresenceAbsenceTerm.NATURALISED()));
141 142
        filteredDistributions.add(Distribution.NewInstance(bahamas, PresenceAbsenceTerm.NATIVE()));
......
144 145
        CondensedDistribution condensedDistribution = composer.createCondensedDistribution(filteredDistributions, null);
145 146
        String condensedString = condensedDistribution.toString();
146 147

  
147
        Assert.assertEquals("Condensed string for Cuba differs", "nCu((c)CuE(nHo)) "+composer.getInternalAreaSeparator() +"Bah ?VM ", condensedString);
148
        Assert.assertEquals("Condensed string for Cuba differs", "n<b>Cu</b>(-d<b>CuW</b>(-c<b>PR*</b>) (c)<b>CuE</b>(n<b>Ho</b>)) " + composer.getInternalAreaSeparator() + "<b>Bah</b> ?<b>VM</b> ", condensedString);
148 149

  
149 150

  
150 151
        //TODO work in progress
......
172 173
        abbrev = "CuW";
173 174
        uuid = UUID.randomUUID();
174 175
        westernCuba = getNamedArea(uuid, label, abbrev, cubaAreasVocabualary);
175
        cuba.addIncludes(westernCuba);
176
//        cuba.addIncludes(westernCuba);
176 177

  
177 178
        //Central Cuba
178 179
        label = "Central Cuba";
......
188 189
        eastCuba = getNamedArea(uuid, label, abbrev, cubaAreasVocabualary);
189 190
        cuba.addIncludes(eastCuba);
190 191

  
192
        cuba.addIncludes(westernCuba);
193

  
194

  
191 195
        //Pinar del Río PR
192 196
        label = "Pinar del Río";
193 197
        abbrev = "PR*";

Also available in: Unified diff