Project

General

Profile

Download (15.9 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
 * Copyright (C) 2009 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.awt.Color;
13
import java.io.IOException;
14
import java.io.Reader;
15
import java.util.ArrayList;
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.IDescriptionService;
33
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
34
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO;
35
import eu.etaxonomy.cdm.api.service.dto.DistributionInfoDTO.InfoPart;
36
import eu.etaxonomy.cdm.api.utility.DescriptionUtility;
37
import eu.etaxonomy.cdm.api.utility.DistributionOrder;
38
import eu.etaxonomy.cdm.model.common.CdmBase;
39
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.common.MarkerType;
42
import eu.etaxonomy.cdm.model.common.TermVocabulary;
43
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
44
import eu.etaxonomy.cdm.model.description.Distribution;
45
import eu.etaxonomy.cdm.model.description.Feature;
46
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
47
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
48
import eu.etaxonomy.cdm.model.description.TaxonDescription;
49
import eu.etaxonomy.cdm.model.location.NamedArea;
50
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
51
import eu.etaxonomy.cdm.model.location.Point;
52
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
53
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
54
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
55
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
56
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
57
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
58
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
59
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
60

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

    
71
    @Autowired
72
    private IDescriptionDao dao;
73

    
74
    @Autowired
75
    private IGeoServiceAreaMapping areaMapping;
76

    
77
    @Autowired
78
    private IDescriptionService descriptionService;
79

    
80
    @Autowired
81
    private ITermVocabularyDao vocabDao;
82

    
83
    private IDefinedTermDao termDao;
84
    @Autowired
85
    public void setTermDao(IDefinedTermDao termDao) {
86
        this.termDao = termDao;
87
        EditGeoServiceUtilities.setTermDao(termDao);
88
    }
89

    
90
    @Autowired
91
    private IOccurrenceDao occurrenceDao;
92

    
93
    private Set<Feature> getDistributionFeatures() {
94
        Set<Feature> distributionFeature = new HashSet<Feature>();
95
        Feature feature = (Feature) termDao.findByUuid(Feature.DISTRIBUTION().getUuid());
96
        distributionFeature.add(feature);
97
        return distributionFeature;
98
    }
99

    
100
    /**
101
     * @param taxonDescriptions
102
     * @return
103
     */
104
    private Set<Distribution> getDistributionsOf(List<TaxonDescription> taxonDescriptions) {
105
        Set<Distribution> result = new HashSet<Distribution>();
106

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

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

    
146
        Set<Distribution> distributions = getDistributionsOf(taxonDescriptions);
147

    
148
        String uriParams = getDistributionServiceRequestParameterString(distributions,
149
                subAreaPreference,
150
                statusOrderPreference,
151
                hideMarkedAreas,
152
                presenceAbsenceTermColors,
153
                langs);
154

    
155
        return uriParams;
156
    }
157

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

    
170
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distributions,
171
                hideMarkedAreas, true, statusOrderPreference, subAreaPreference);
172

    
173

    
174
        String uriParams = EditGeoServiceUtilities.getDistributionServiceRequestParameterString(
175
                filteredDistributions,
176
                areaMapping,
177
                presenceAbsenceTermColors,
178
                null, langs);
179
        return uriParams;
180
    }
181

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

    
194
        List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();
195
        taxonDescriptions.add(taxonDescription);
196

    
197
        return getDistributionServiceRequestParameterString(taxonDescriptions,
198
                subAreaPreference,
199
                statusOrderPreference,
200
                hideMarkedAreas,
201
                presenceAbsenceTermColors,
202
                langs);
203
    }
204

    
205
    /**
206
     * {@inheritDoc}
207
     */
208
    @Override
209
    public OccurrenceServiceRequestParameterDto getOccurrenceServiceRequestParameterString(List<SpecimenOrObservationBase> specimensOrObersvations,
210
            Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors) {
211

    
212
        List<Point> fieldUnitPoints = new ArrayList<Point>();
213
        List<Point> derivedUnitPoints = new ArrayList<Point>();
214

    
215
        IndividualsAssociation individualsAssociation;
216
        DerivedUnit derivedUnit;
217

    
218
        for (SpecimenOrObservationBase specimenOrObservationBase : specimensOrObersvations) {
219
            SpecimenOrObservationBase<?> specimenOrObservation = occurrenceDao
220
                    .load(specimenOrObservationBase.getUuid());
221

    
222
            if (specimenOrObservation instanceof FieldUnit) {
223
                fieldUnitPoints.add(((FieldUnit) specimenOrObservation).getGatheringEvent()
224
                        .getExactLocation());
225
            }
226
            if (specimenOrObservation instanceof DerivedUnit) {
227
                registerDerivedUnitLocations((DerivedUnit) specimenOrObservation, derivedUnitPoints);
228
            }
229
        }
230

    
231
        return EditGeoServiceUtilities.getOccurrenceServiceRequestParameterString(fieldUnitPoints,
232
                derivedUnitPoints, specimenOrObservationTypeColors);
233

    
234
    }
235

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

    
247
    public CondensedDistribution getCondensedDistribution(Set<Distribution> distributions,
248
            boolean statusOrderPreference,
249
            Set<MarkerType> hideMarkedAreas,
250
            MarkerType fallbackAreaMarkerType,
251
            CondensedDistributionRecipe recipe,
252
            List<Language> langs) {
253

    
254
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(
255
                distributions, hideMarkedAreas, true, statusOrderPreference, false);
256

    
257

    
258

    
259
        CondensedDistribution condensedDistribution = EditGeoServiceUtilities.getCondensedDistribution(
260
                filteredDistributions,
261
                recipe,
262
                langs);
263

    
264
        return condensedDistribution;
265
    }
266

    
267
    /**
268
     * @param derivedUnit
269
     * @param derivedUnitPoints
270
     */
271
    private void registerDerivedUnitLocations(DerivedUnit derivedUnit, List<Point> derivedUnitPoints) {
272

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

    
300
    }
301

    
302

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

    
310
    }
311

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

    
321
        Set<NamedArea> areas = new HashSet<NamedArea>();
322

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

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

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

    
352
        DistributionInfoDTO dto = new DistributionInfoDTO();
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
}
(2-2/11)