Project

General

Profile

Download (15.9 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2009 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.awt.Color;
12
import java.io.IOException;
13
import java.io.Reader;
14
import java.util.ArrayList;
15
import java.util.Arrays;
16
import java.util.Collection;
17
import java.util.EnumSet;
18
import java.util.HashSet;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Set;
22
import java.util.UUID;
23

    
24
import javax.persistence.EntityNotFoundException;
25

    
26
import org.apache.log4j.Logger;
27
import org.springframework.beans.factory.annotation.Autowired;
28
import org.springframework.stereotype.Service;
29
import org.springframework.transaction.annotation.Transactional;
30

    
31
import eu.etaxonomy.cdm.api.service.DistributionTree;
32
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
33
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO;
34
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO.InfoPart;
35
import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
36
import eu.etaxonomy.cdm.api.utility.DistributionOrder;
37
import eu.etaxonomy.cdm.model.common.CdmBase;
38
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
39
import eu.etaxonomy.cdm.model.common.Language;
40
import eu.etaxonomy.cdm.model.common.MarkerType;
41
import eu.etaxonomy.cdm.model.common.TermVocabulary;
42
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
43
import eu.etaxonomy.cdm.model.description.Distribution;
44
import eu.etaxonomy.cdm.model.description.Feature;
45
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
46
import eu.etaxonomy.cdm.model.description.TaxonDescription;
47
import eu.etaxonomy.cdm.model.location.NamedArea;
48
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
49
import eu.etaxonomy.cdm.model.location.Point;
50
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
51
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
52
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
53
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
54
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
55
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
56
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
57
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
58
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
59

    
60
/**
61
 * @author a.kohlbecker
62
 * @date 18.06.2009
63
 *
64
 */
65
@Service
66
@Transactional(readOnly = true)
67
public class EditGeoService implements IEditGeoService {
68
    public static final Logger logger = Logger.getLogger(EditGeoService.class);
69

    
70
    @Autowired
71
    private IDescriptionDao dao;
72

    
73
    @Autowired
74
    private IGeoServiceAreaMapping areaMapping;
75

    
76
    @Autowired
77
    private ITermVocabularyDao vocabDao;
78

    
79
    private IDefinedTermDao termDao;
80
    @Autowired
81
    public void setTermDao(IDefinedTermDao termDao) {
82
        this.termDao = termDao;
83
        EditGeoServiceUtilities.setTermDao(termDao);
84
    }
85

    
86
    @Autowired
87
    private IOccurrenceDao occurrenceDao;
88

    
89
    private Set<Feature> getDistributionFeatures() {
90
        Set<Feature> distributionFeature = new HashSet<Feature>();
91
        Feature feature = (Feature) termDao.findByUuid(Feature.DISTRIBUTION().getUuid());
92
        distributionFeature.add(feature);
93
        return distributionFeature;
94
    }
95

    
96
    /**
97
     * @param taxonDescriptions
98
     * @return
99
     */
100
    private Set<Distribution> getDistributionsOf(List<TaxonDescription> taxonDescriptions) {
101
        Set<Distribution> result = new HashSet<Distribution>();
102

    
103
        Set<Feature> features = getDistributionFeatures();
104
        for (TaxonDescription taxonDescription : taxonDescriptions) {
105
            List<Distribution> distributions;
106
            if (taxonDescription.getId() > 0){
107
                distributions = dao.getDescriptionElements(
108
                        taxonDescription,
109
                        null,
110
                        null /*features*/,
111
                        Distribution.class,
112
                        null,
113
                        null,
114
                        null);
115
            }else{
116
                distributions = new ArrayList<Distribution>();
117
                for (DescriptionElementBase deb : taxonDescription.getElements()){
118
                    if (deb.isInstanceOf(Distribution.class)){
119
                        if (features == null || features.isEmpty()
120
                                || features.contains(deb.getFeature())) {
121
                            distributions.add(CdmBase.deproxy(deb, Distribution.class));
122
                        }
123
                    }
124
                }
125
            }
126
            result.addAll(distributions);
127
        }
128
        return result;
129
    }
130

    
131
    /**
132
     * {@inheritDoc}
133
     */
134
    @Override
135
    public String getDistributionServiceRequestParameterString(List<TaxonDescription> taxonDescriptions,
136
            boolean subAreaPreference,
137
            boolean statusOrderPreference,
138
            Set<MarkerType> hideMarkedAreas,
139
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
140
            List<Language> langs) {
141

    
142
        Set<Distribution> distributions = getDistributionsOf(taxonDescriptions);
143

    
144
        String uriParams = getDistributionServiceRequestParameterString(distributions,
145
                subAreaPreference,
146
                statusOrderPreference,
147
                hideMarkedAreas,
148
                presenceAbsenceTermColors,
149
                langs);
150

    
151
        return uriParams;
152
    }
153

    
154
    /**
155
     * {@inheritDoc}
156
     */
157
    @Override
158
    public String getDistributionServiceRequestParameterString(
159
            Set<Distribution> distributions,
160
            boolean subAreaPreference,
161
            boolean statusOrderPreference,
162
            Set<MarkerType> hideMarkedAreas,
163
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
164
            List<Language> langs) {
165

    
166
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distributions,
167
                hideMarkedAreas, true, statusOrderPreference, subAreaPreference);
168

    
169

    
170
        String uriParams = EditGeoServiceUtilities.getDistributionServiceRequestParameterString(
171
                filteredDistributions,
172
                areaMapping,
173
                presenceAbsenceTermColors,
174
                null, langs);
175
        return uriParams;
176
    }
177

    
178
    /**
179
     * {@inheritDoc}
180
     */
181
    @Override
182
    @Deprecated
183
    public String getDistributionServiceRequestParameterString(TaxonDescription taxonDescription,
184
            boolean subAreaPreference,
185
            boolean statusOrderPreference,
186
            Set<MarkerType> hideMarkedAreas,
187
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
188
            List<Language> langs) {
189

    
190
        List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();
191
        taxonDescriptions.add(taxonDescription);
192

    
193
        return getDistributionServiceRequestParameterString(taxonDescriptions,
194
                subAreaPreference,
195
                statusOrderPreference,
196
                hideMarkedAreas,
197
                presenceAbsenceTermColors,
198
                langs);
199
    }
200

    
201
    /**
202
     * {@inheritDoc}
203
     */
204
    @Override
205
    public OccurrenceServiceRequestParameterDto getOccurrenceServiceRequestParameterString(
206
            List<SpecimenOrObservationBase> specimensOrObersvations,
207
            Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors) {
208

    
209
        List<Point> fieldUnitPoints = new ArrayList<>();
210
        List<Point> derivedUnitPoints = new ArrayList<>();
211

    
212
        for (SpecimenOrObservationBase<?> specimenOrObservationBase : specimensOrObersvations) {
213
            SpecimenOrObservationBase<?> specimenOrObservation = occurrenceDao
214
                    .load(specimenOrObservationBase.getUuid());
215

    
216
            if (specimenOrObservation instanceof FieldUnit) {
217
                GatheringEvent gatherEvent = ((FieldUnit) specimenOrObservation).getGatheringEvent();
218
                if (gatherEvent != null && gatherEvent.getExactLocation() != null){
219
                    fieldUnitPoints.add(gatherEvent.getExactLocation());
220
                }
221
            }
222
            if (specimenOrObservation instanceof DerivedUnit) {
223
                registerDerivedUnitLocations((DerivedUnit) specimenOrObservation, derivedUnitPoints);
224
            }
225
        }
226

    
227
        return EditGeoServiceUtilities.getOccurrenceServiceRequestParameterString(fieldUnitPoints,
228
                derivedUnitPoints, specimenOrObservationTypeColors);
229

    
230
    }
231

    
232
    public CondensedDistribution getCondensedDistribution(List<TaxonDescription> taxonDescriptions,
233
            boolean statusOrderPreference,
234
            Set<MarkerType> hideMarkedAreas,
235
            MarkerType fallbackAreaMarkerType,
236
            CondensedDistributionRecipe recipe,
237
            List<Language> langs) {
238
        Set<Distribution> distributions = getDistributionsOf(taxonDescriptions);
239
        return getCondensedDistribution(distributions, statusOrderPreference,
240
                hideMarkedAreas, fallbackAreaMarkerType, recipe, langs);
241
    }
242

    
243
    @Override
244
    public CondensedDistribution getCondensedDistribution(Set<Distribution> distributions,
245
            boolean statusOrderPreference,
246
            Set<MarkerType> hideMarkedAreas,
247
            MarkerType fallbackAreaMarkerType,
248
            CondensedDistributionRecipe recipe,
249
            List<Language> langs) {
250

    
251
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(
252
                distributions, hideMarkedAreas, true, statusOrderPreference, false);
253

    
254

    
255

    
256
        CondensedDistribution condensedDistribution = EditGeoServiceUtilities.getCondensedDistribution(
257
                filteredDistributions,
258
                recipe,
259
                langs);
260

    
261
        return condensedDistribution;
262
    }
263

    
264
    /**
265
     * @param derivedUnit
266
     * @param derivedUnitPoints
267
     */
268
    private void registerDerivedUnitLocations(DerivedUnit derivedUnit, List<Point> derivedUnitPoints) {
269

    
270
        Set<SpecimenOrObservationBase> originals = derivedUnit.getOriginals();
271
        if (originals != null) {
272
            for (SpecimenOrObservationBase<?> original : originals) {
273
                if (original instanceof FieldUnit) {
274
                    if (((FieldUnit) original).getGatheringEvent() != null) {
275
                        Point point = ((FieldUnit) original).getGatheringEvent().getExactLocation();
276
                        if (point != null) {
277
                            // points with no longitude or latitude should not exist
278
                            // see  #4173 ([Rule] Longitude and Latitude in Point must not be null)
279
                            if (point.getLatitude() == null || point.getLongitude() == null){
280
                                continue;
281
                            }
282
                            // FIXME: remove next statement after
283
                            // DerivedUnitFacade or ABCD import is fixed
284
                            //
285
                            if(point.getLatitude() == 0.0 || point.getLongitude() == 0.0) {
286
                                continue;
287
                            }
288
                            derivedUnitPoints.add(point);
289
                        }
290
                    }
291
                } else {
292
                    registerDerivedUnitLocations((DerivedUnit) original, derivedUnitPoints);
293
                }
294
            }
295
        }
296

    
297
    }
298

    
299

    
300
    /**
301
     * {@inheritDoc}
302
     */
303
    @Override
304
    public void setMapping(NamedArea area, GeoServiceArea geoServiceArea) {
305
        areaMapping.set(area, geoServiceArea);
306

    
307
    }
308

    
309
    /**
310
     * {@inheritDoc}
311
     */
312
    @Override
313
    @Transactional(readOnly=false)
314
    public Map<NamedArea, String> mapShapeFileToNamedAreas(Reader csvReader,
315
            List<String> idSearchFields, String wmsLayerName, UUID areaVocabularyUuid,
316
            Set<UUID> namedAreaUuids) throws IOException {
317

    
318
        Set<NamedArea> areas = new HashSet<NamedArea>();
319

    
320
        if(areaVocabularyUuid != null){
321
            TermVocabulary<NamedArea> areaVocabulary = vocabDao.load(areaVocabularyUuid);
322
            if(areaVocabulary == null){
323
                throw new EntityNotFoundException("No Vocabulary found for uuid " + areaVocabularyUuid);
324
            }
325
            areas.addAll(areaVocabulary.getTerms());
326
        }
327
        if(namedAreaUuids != null && !namedAreaUuids.isEmpty()){
328
            for(DefinedTermBase<?> dtb : termDao.list(namedAreaUuids, null, null, null, null)){
329
                areas.add((NamedArea)dtb);
330
            }
331
        }
332

    
333
        ShpAttributesToNamedAreaMapper mapper = new ShpAttributesToNamedAreaMapper(areas, areaMapping);
334
        Map<NamedArea, String> resultMap = mapper.readCsv(csvReader, idSearchFields, wmsLayerName);
335
        termDao.saveOrUpdateAll((Collection)areas);
336
        return resultMap;
337
    }
338

    
339
    /**
340
     * {@inheritDoc}
341
     */
342
    @Override
343
    public DistributionInfoDTO composeDistributionInfoFor(EnumSet<DistributionInfoDTO.InfoPart> parts, UUID taxonUUID,
344
            boolean subAreaPreference, boolean statusOrderPreference, Set<MarkerType> hiddenAreaMarkerTypes,
345
            Set<NamedAreaLevel> omitLevels, Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
346
            List<Language> languages,  List<String> propertyPaths, CondensedDistributionRecipe recipe,
347
            DistributionOrder distributionOrder){
348

    
349
        DistributionInfoDTO dto = new DistributionInfoDTO();
350

    
351
        if (propertyPaths == null){
352
            propertyPaths = Arrays.asList(new String []{});
353
        }
354
        // Adding default initStrategies to improve the performance of this method
355
        // adding 'status' and 'area' has a good positive effect:
356
        // filterDistributions() only takes 21% of the total method time (before it was 46%)
357
        // at the same time the cost of the getDescriptionElementForTaxon is not increased at all!
358
        //
359
        // adding 'markers.markerType' is not improving the performance since it only
360
        // moved the load from the filter method to the getDescriptionElementForTaxon()
361
        // method.
362
        // overall improvement by this means is by 42% (from 77,711 ms to 44,868 ms)
363
        ArrayList<String> initStrategy = new ArrayList<String>(propertyPaths);
364
        if(!initStrategy.contains("status")) {
365
            initStrategy.add("status");
366
        }
367
        if(!initStrategy.contains("area")) {
368
            initStrategy.add("area");
369
        }
370
        if(!initStrategy.contains("markers.markerType")) {
371
            initStrategy.add("markers.markerType");
372
        }
373
        if(omitLevels == null) {
374
            omitLevels = new HashSet<NamedAreaLevel>(0);
375
        }
376

    
377
        List<Distribution> distributions = dao.getDescriptionElementForTaxon(taxonUUID, null, Distribution.class, null, null, initStrategy);
378

    
379
        // Apply the rules statusOrderPreference and hideMarkedAreas for textual distribution info
380
        Set<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distributions, hiddenAreaMarkerTypes,
381
                true, statusOrderPreference, false);
382

    
383
        if(parts.contains(InfoPart.elements)) {
384
            dto.setElements(filteredDistributions);
385
        }
386

    
387
        if(parts.contains(InfoPart.tree)) {
388
            DistributionTree tree = DescriptionUtility.orderDistributions(termDao, omitLevels, filteredDistributions, hiddenAreaMarkerTypes,distributionOrder);
389
            dto.setTree(tree);
390
        }
391

    
392
        if(parts.contains(InfoPart.condensedDistribution)) {
393
            dto.setCondensedDistribution(EditGeoServiceUtilities.getCondensedDistribution(filteredDistributions, recipe, languages));
394
        }
395

    
396
        if (parts.contains(InfoPart.mapUriParams)) {
397
            // only apply the subAreaPreference rule for the maps
398
            Set<Distribution> filteredMapDistributions = DescriptionUtility.filterDistributions(filteredDistributions, null, false, false, subAreaPreference);
399

    
400
            dto.setMapUriParams(EditGeoServiceUtilities.getDistributionServiceRequestParameterString(filteredMapDistributions,
401
                    areaMapping,
402
                    presenceAbsenceTermColors,
403
                    null, languages));
404
        }
405

    
406
        return dto;
407
    }
408
}
(3-3/14)