Project

General

Profile

Download (15.3 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.IDescriptionService;
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.model.common.DefinedTermBase;
37
import eu.etaxonomy.cdm.model.common.Language;
38
import eu.etaxonomy.cdm.model.common.MarkerType;
39
import eu.etaxonomy.cdm.model.common.TermVocabulary;
40
import eu.etaxonomy.cdm.model.description.Distribution;
41
import eu.etaxonomy.cdm.model.description.Feature;
42
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
43
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
44
import eu.etaxonomy.cdm.model.description.TaxonDescription;
45
import eu.etaxonomy.cdm.model.location.NamedArea;
46
import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
47
import eu.etaxonomy.cdm.model.location.Point;
48
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
49
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
50
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
51
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
52
import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
53
import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
54
import eu.etaxonomy.cdm.persistence.dao.description.IDescriptionDao;
55
import eu.etaxonomy.cdm.persistence.dao.occurrence.IOccurrenceDao;
56

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

    
67
    @Autowired
68
    private IDescriptionDao dao;
69

    
70
    @Autowired
71
    private IGeoServiceAreaMapping areaMapping;
72

    
73
    @Autowired
74
    private IDescriptionService descriptionService;
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> distributions = new HashSet<Distribution>();
102
        for (TaxonDescription taxonDescription : taxonDescriptions) {
103
            List<Distribution> result = (List) dao.getDescriptionElements(
104
                    taxonDescription,
105
                    null,
106
                    getDistributionFeatures(),
107
                    Distribution.class,
108
                    null,
109
                    null,
110
                    null);
111
            distributions.addAll(result);
112
        }
113
        return distributions;
114
    }
115

    
116
    /**
117
     * {@inheritDoc}
118
     */
119
    @Override
120
    public String getDistributionServiceRequestParameterString(List<TaxonDescription> taxonDescriptions,
121
            boolean subAreaPreference,
122
            boolean statusOrderPreference,
123
            Set<MarkerType> hideMarkedAreas,
124
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
125
            List<Language> langs) {
126

    
127
        Set<Distribution> distributions = getDistributionsOf(taxonDescriptions);
128

    
129
        String uriParams = getDistributionServiceRequestParameterString(distributions,
130
                subAreaPreference,
131
                statusOrderPreference,
132
                hideMarkedAreas,
133
                presenceAbsenceTermColors,
134
                langs);
135

    
136
        return uriParams;
137
    }
138

    
139
    /**
140
     * {@inheritDoc}
141
     */
142
    @Override
143
    public String getDistributionServiceRequestParameterString(
144
            Set<Distribution> distributions,
145
            boolean subAreaPreference,
146
            boolean statusOrderPreference,
147
            Set<MarkerType> hideMarkedAreas,
148
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
149
            List<Language> langs) {
150

    
151
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distributions,
152
                hideMarkedAreas, true, statusOrderPreference, subAreaPreference);
153

    
154

    
155
        String uriParams = EditGeoServiceUtilities.getDistributionServiceRequestParameterString(
156
                filteredDistributions,
157
                areaMapping,
158
                presenceAbsenceTermColors,
159
                null, langs);
160
        return uriParams;
161
    }
162

    
163
    /**
164
     * {@inheritDoc}
165
     */
166
    @Override
167
    @Deprecated
168
    public String getDistributionServiceRequestParameterString(TaxonDescription taxonDescription,
169
            boolean subAreaPreference,
170
            boolean statusOrderPreference,
171
            Set<MarkerType> hideMarkedAreas,
172
            Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
173
            List<Language> langs) {
174

    
175
        List<TaxonDescription> taxonDescriptions = new ArrayList<TaxonDescription>();
176
        taxonDescriptions.add(taxonDescription);
177

    
178
        return getDistributionServiceRequestParameterString(taxonDescriptions,
179
                subAreaPreference,
180
                statusOrderPreference,
181
                hideMarkedAreas,
182
                presenceAbsenceTermColors,
183
                langs);
184
    }
185

    
186
    /**
187
     * {@inheritDoc}
188
     */
189
    @Override
190
    public OccurrenceServiceRequestParameterDto getOccurrenceServiceRequestParameterString(List<SpecimenOrObservationBase> specimensOrObersvations,
191
            Map<SpecimenOrObservationType, Color> specimenOrObservationTypeColors) {
192

    
193
        List<Point> fieldUnitPoints = new ArrayList<Point>();
194
        List<Point> derivedUnitPoints = new ArrayList<Point>();
195

    
196
        IndividualsAssociation individualsAssociation;
197
        DerivedUnit derivedUnit;
198

    
199
        for (SpecimenOrObservationBase specimenOrObservationBase : specimensOrObersvations) {
200
            SpecimenOrObservationBase<?> specimenOrObservation = occurrenceDao
201
                    .load(specimenOrObservationBase.getUuid());
202

    
203
            if (specimenOrObservation instanceof FieldUnit) {
204
                fieldUnitPoints.add(((FieldUnit) specimenOrObservation).getGatheringEvent()
205
                        .getExactLocation());
206
            }
207
            if (specimenOrObservation instanceof DerivedUnit) {
208
                registerDerivedUnitLocations((DerivedUnit) specimenOrObservation, derivedUnitPoints);
209
            }
210
        }
211

    
212
        return EditGeoServiceUtilities.getOccurrenceServiceRequestParameterString(fieldUnitPoints,
213
                derivedUnitPoints, specimenOrObservationTypeColors);
214

    
215
    }
216

    
217
    public CondensedDistribution getCondensedDistribution(List<TaxonDescription> taxonDescriptions,
218
            boolean statusOrderPreference,
219
            Set<MarkerType> hideMarkedAreas,
220
            MarkerType fallbackAreaMarkerType,
221
            CondensedDistributionRecipe recipe,
222
            List<Language> langs) {
223
        Set<Distribution> distributions = getDistributionsOf(taxonDescriptions);
224
        return getCondensedDistribution(distributions, statusOrderPreference,
225
                hideMarkedAreas, fallbackAreaMarkerType, recipe, langs);
226
    }
227

    
228
    public CondensedDistribution getCondensedDistribution(Set<Distribution> distributions,
229
            boolean statusOrderPreference,
230
            Set<MarkerType> hideMarkedAreas,
231
            MarkerType fallbackAreaMarkerType,
232
            CondensedDistributionRecipe recipe,
233
            List<Language> langs) {
234

    
235
        Collection<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(
236
                distributions, hideMarkedAreas, true, statusOrderPreference, false);
237

    
238

    
239

    
240
        CondensedDistribution condensedDistribution = EditGeoServiceUtilities.getCondensedDistribution(
241
                filteredDistributions,
242
                recipe,
243
                langs);
244

    
245
        return condensedDistribution;
246
    }
247

    
248
    /**
249
     * @param derivedUnit
250
     * @param derivedUnitPoints
251
     */
252
    private void registerDerivedUnitLocations(DerivedUnit derivedUnit, List<Point> derivedUnitPoints) {
253

    
254
        Set<SpecimenOrObservationBase> originals = derivedUnit.getOriginals();
255
        if (originals != null) {
256
            for (SpecimenOrObservationBase original : originals) {
257
                if (original instanceof FieldUnit) {
258
                    if (((FieldUnit) original).getGatheringEvent() != null) {
259
                        Point point = ((FieldUnit) original).getGatheringEvent().getExactLocation();
260
                        if (point != null) {
261
                            // points with no longitude or latitude should not exist
262
                            // see  #4173 ([Rule] Longitude and Latitude in Point must not be null)
263
                            if (point.getLatitude() == null || point.getLongitude() == null){
264
                                continue;
265
                            }
266
                            // FIXME: remove next statement after
267
                            // DerivedUnitFacade or ABCD import is fixed
268
                            //
269
                            if(point.getLatitude() == 0.0 || point.getLongitude() == 0.0) {
270
                                continue;
271
                            }
272
                            derivedUnitPoints.add(point);
273
                        }
274
                    }
275
                } else {
276
                    registerDerivedUnitLocations((DerivedUnit) original, derivedUnitPoints);
277
                }
278
            }
279
        }
280

    
281
    }
282

    
283

    
284
    /**
285
     * {@inheritDoc}
286
     */
287
    @Override
288
    public void setMapping(NamedArea area, GeoServiceArea geoServiceArea) {
289
        areaMapping.set(area, geoServiceArea);
290

    
291
    }
292

    
293
    /**
294
     * {@inheritDoc}
295
     */
296
    @Override
297
    @Transactional(readOnly=false)
298
    public Map<NamedArea, String> mapShapeFileToNamedAreas(Reader csvReader,
299
            List<String> idSearchFields, String wmsLayerName, UUID areaVocabularyUuid,
300
            Set<UUID> namedAreaUuids) throws IOException {
301

    
302
        Set<NamedArea> areas = new HashSet<NamedArea>();
303

    
304
        if(areaVocabularyUuid != null){
305
            TermVocabulary<NamedArea> areaVocabulary = vocabDao.load(areaVocabularyUuid);
306
            if(areaVocabulary == null){
307
                throw new EntityNotFoundException("No Vocabulary found for uuid " + areaVocabularyUuid);
308
            }
309
            areas.addAll(areaVocabulary.getTerms());
310
        }
311
        if(namedAreaUuids != null && !namedAreaUuids.isEmpty()){
312
            for(DefinedTermBase dtb : termDao.list(namedAreaUuids, null, null, null, null)){
313
                areas.add((NamedArea)dtb);
314
            }
315
        }
316

    
317
        ShpAttributesToNamedAreaMapper mapper = new ShpAttributesToNamedAreaMapper(areas, areaMapping);
318
        Map<NamedArea, String> resultMap = mapper.readCsv(csvReader, idSearchFields, wmsLayerName);
319
        termDao.saveOrUpdateAll((Collection)areas);
320
        return resultMap;
321
    }
322

    
323
    /**
324
     * {@inheritDoc}
325
     */
326
    @Override
327
    public DistributionInfoDTO composeDistributionInfoFor(EnumSet<DistributionInfoDTO.InfoPart> parts, UUID taxonUUID,
328
            boolean subAreaPreference, boolean statusOrderPreference, Set<MarkerType> hiddenAreaMarkerTypes,
329
            Set<NamedAreaLevel> omitLevels, Map<PresenceAbsenceTerm, Color> presenceAbsenceTermColors,
330
            List<Language> languages,  List<String> propertyPaths, CondensedDistributionRecipe recipe){
331

    
332
        DistributionInfoDTO dto = new DistributionInfoDTO();
333

    
334
        // Adding default initStrategies to improve the performance of this method
335
        // adding 'status' and 'area' has a good positive effect:
336
        // filterDistributions() only takes 21% of the total method time (before it was 46%)
337
        // at the same time the cost of the getDescriptionElementForTaxon is not increased at all!
338
        //
339
        // adding 'markers.markerType' is not improving the performance since it only
340
        // moved the load from the filter method to the getDescriptionElementForTaxon()
341
        // method.
342
        // overall improvement by this means is by 42% (from 77,711 ms to 44,868 ms)
343
        ArrayList<String> initStrategy = new ArrayList<String>(propertyPaths);
344
        if(!initStrategy.contains("status")) {
345
            initStrategy.add("status");
346
        }
347
        if(!initStrategy.contains("area")) {
348
            initStrategy.add("area");
349
        }
350
        if(!initStrategy.contains("markers.markerType")) {
351
            initStrategy.add("markers.markerType");
352
        }
353
        if(omitLevels == null) {
354
            omitLevels = new HashSet<NamedAreaLevel>(0);
355
        }
356

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

    
359
        // Apply the rules statusOrderPreference and hideMarkedAreas for textual distribution info
360
        Set<Distribution> filteredDistributions = DescriptionUtility.filterDistributions(distributions, hiddenAreaMarkerTypes,
361
                true, statusOrderPreference, false);
362

    
363
        if(parts.contains(InfoPart.elements)) {
364
            dto.setElements(filteredDistributions);
365
        }
366

    
367
        if(parts.contains(InfoPart.tree)) {
368
            dto.setTree(DescriptionUtility.orderDistributions(termDao, omitLevels, filteredDistributions, hiddenAreaMarkerTypes));
369
        }
370

    
371
        if(parts.contains(InfoPart.condensedDistribution)) {
372
            dto.setCondensedDistribution(EditGeoServiceUtilities.getCondensedDistribution(filteredDistributions, recipe, languages));
373
        }
374

    
375
        if (parts.contains(InfoPart.mapUriParams)) {
376
            // only apply the subAreaPreference rule for the maps
377
            Set<Distribution> filteredMapDistributions = DescriptionUtility.filterDistributions(filteredDistributions, null, false, false, subAreaPreference);
378

    
379
            dto.setMapUriParams(EditGeoServiceUtilities.getDistributionServiceRequestParameterString(filteredMapDistributions,
380
                    areaMapping,
381
                    presenceAbsenceTermColors,
382
                    null, languages));
383
        }
384

    
385
        return dto;
386
    }
387
}
(2-2/11)