Project

General

Profile

Download (18.4 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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.vaadin.view.distributionStatus;
10

    
11
import java.sql.SQLException;
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.HashMap;
17
import java.util.HashSet;
18
import java.util.List;
19
import java.util.Set;
20
import java.util.UUID;
21
import java.util.stream.Collectors;
22

    
23
import org.springframework.beans.factory.annotation.Autowired;
24
import org.springframework.beans.factory.annotation.Qualifier;
25
import org.springframework.transaction.TransactionStatus;
26
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
27
import org.vaadin.addons.lazyquerycontainer.QueryDefinition;
28
import org.vaadin.addons.lazyquerycontainer.QueryFactory;
29
import org.vaadin.spring.events.EventBus.ViewEventBus;
30

    
31
import com.vaadin.server.VaadinSession;
32
import com.vaadin.spring.annotation.SpringComponent;
33
import com.vaadin.spring.annotation.ViewScope;
34
import com.vaadin.ui.Notification;
35

    
36
import eu.etaxonomy.cdm.api.application.CdmRepository;
37
import eu.etaxonomy.cdm.i18n.Messages;
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.OrderedTermVocabulary;
42
import eu.etaxonomy.cdm.model.common.Representation;
43
import eu.etaxonomy.cdm.model.common.TermVocabulary;
44
import eu.etaxonomy.cdm.model.description.DescriptionBase;
45
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
46
import eu.etaxonomy.cdm.model.description.Distribution;
47
import eu.etaxonomy.cdm.model.description.Feature;
48
import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
49
import eu.etaxonomy.cdm.model.description.TaxonDescription;
50
import eu.etaxonomy.cdm.model.location.NamedArea;
51
import eu.etaxonomy.cdm.model.taxon.Classification;
52
import eu.etaxonomy.cdm.model.taxon.Taxon;
53
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
54
import eu.etaxonomy.cdm.service.CdmUserHelper;
55
import eu.etaxonomy.cdm.vaadin.container.CdmSQLContainer;
56
import eu.etaxonomy.cdm.vaadin.container.PresenceAbsenceTermContainer;
57
import eu.etaxonomy.cdm.vaadin.util.CdmQueryFactory;
58
import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
59
import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
60
import eu.etaxonomy.cdm.vaadin.util.DistributionStatusQueryDefinition;
61
import eu.etaxonomy.cdm.vaadin.util.DistributionStatusQueryFactory;
62
import eu.etaxonomy.vaadin.mvp.AbstractPresenter;
63

    
64
/**
65
 * The presenter of the distribution status editor. 
66
 * 
67
 */
68
@SpringComponent
69
@ViewScope
70
public class DistributionTablePresenter extends AbstractPresenter<IDistributionTableView> {
71

    
72
	private static final long serialVersionUID = 3313043335587777217L;
73

    
74
    @Autowired
75
    private CdmUserHelper userHelper;
76

    
77
    @Autowired
78
    @Qualifier("cdmRepository")
79
    private CdmRepository repo; // TODO remove, since this is already in the super class
80

    
81
	/**
82
     * {@inheritDoc}
83
     */
84
    @Override
85
    protected void eventViewBusSubscription(ViewEventBus viewEventBus) {
86
        // no point subscribing
87
    }
88

    
89
    /**
90
     * Changes the distribution status of the given {@link Taxon} for the given {@link NamedArea} to the sepcified {@link PresenceAbsenceTerm}.  
91
     * @param area The area to update the distribution status for.
92
     * @param distributionStatus The distribution status to update the taxon with.
93
     * @param taxon The taxon to be updated.
94
     * @return 
95
     * {@code 0} if the update was successful. 
96
     * {@code 1} if the distributionStatus was null and the {@link DescriptionElementBase} was deleted successfully.
97
     * {@code -1} if an error occurred.
98
     */
99
    public int updateDistributionField(NamedArea area, PresenceAbsenceTerm distributionStatus, Taxon taxon) {
100
	    TransactionStatus tx = repo.startTransaction();
101
	    taxon = (Taxon)repo.getTaxonService().find(taxon.getUuid());
102
	    if(area==null){
103
	    	Notification.show(Messages.getLocalizedString(Messages.DistributionTablePresenter_ERROR_UPDATE_DISTRIBUTION_TERM));
104
	    	repo.commitTransaction(tx);
105
	    	return -1;
106
	    }
107
	    List<Distribution> distributions = getDistributions(taxon);
108
	    Distribution distribution = null;
109
	    for(Distribution dist : distributions){
110
	        if(dist.getArea()!=null && dist.getArea().equals(area)){
111
	            distribution = dist;
112
	            break;
113
	        }
114
	    }
115
	    if(distribution==null){
116
	    	//create new distribution
117
	    	distribution = Distribution.NewInstance(area, distributionStatus);
118
			Set<TaxonDescription> descriptions = taxon.getDescriptions();
119
			if (descriptions != null && !descriptions.isEmpty()) {
120
			    for (TaxonDescription desc : descriptions) {
121
			        // add to first taxon description
122
			        desc.addElement(distribution);
123
			        repo.commitTransaction(tx);
124
			        return 0;
125
			    }
126
			} else {// there are no TaxonDescription yet.
127
			    TaxonDescription taxonDescription = TaxonDescription.NewInstance(taxon);
128
			    taxonDescription.addElement(distribution);
129
			    repo.commitTransaction(tx);
130
			    return 0;
131
			}
132
	    }
133
	    else if(distributionStatus == null){//delete descriptionElementBase
134
	        DescriptionBase<?> desc = distribution.getInDescription();
135
	        desc.removeElement(distribution);
136
	    	repo.commitTransaction(tx);
137
            return 1;
138
	    }
139
	    else{//update distribution
140
           distribution.setStatus(distributionStatus);
141
           repo.getCommonService().saveOrUpdate(distribution);
142
           repo.commitTransaction(tx);
143
           return 0;
144
        }
145
	    repo.commitTransaction(tx);
146
	    return -1;
147
	}
148

    
149
    /**
150
     * Returns a {@link CdmSQLContainer} containing the distribution status information
151
     * for the chosen {@link TaxonNode}s and {@link NamedArea}s.
152
     * @return  {@link CdmSQLContainer} containing the distribution status information
153
     *  for the chosen {@link TaxonNode}s and {@link NamedArea}s.
154
     * @throws SQLException
155
     */
156
    public CdmSQLContainer getSQLContainer() throws SQLException{
157
         List<Integer> nodeIds = new ArrayList<>();
158
         for (TaxonNode taxonNode : getAllNodes()) {
159
             nodeIds.add(taxonNode.getId());
160
         }
161
         List<NamedArea> namedAreas = getChosenAreas();
162
         if(namedAreas!=null){
163
             return new CdmSQLContainer(CdmQueryFactory.generateTaxonDistributionQuery(nodeIds, namedAreas));
164
         }
165
         return null;
166
    }
167

    
168
    /**
169
     * Returns a {@link PresenceAbsenceTermContainer} containing all allowed and chosen {@link PresenceAbsenceTerm}s. 
170
     * @return {@link PresenceAbsenceTermContainer} containing all allowed and chosen {@link PresenceAbsenceTerm}s.
171
     */
172
    public PresenceAbsenceTermContainer getPresenceAbsenceTermContainer() {
173
        return PresenceAbsenceTermContainer.getInstance();
174
    }
175

    
176
    /**
177
     * Returns a list of {@link DescriptionElementBase}s for the specified {@link Taxon} and {@link Feature} set.
178
     * @param taxon The {@link Taxon} to get the descriptions for.
179
     * @param setFeature The features to get the descriptions for.
180
     * @return List of {@link DescriptionElementBase}s for the specified {@link Taxon} and {@link Feature} set.
181
     */
182
    public List<DescriptionElementBase> listDescriptionElementsForTaxon(Taxon taxon, Set<Feature> setFeature){
183
        List<DescriptionElementBase> listDescriptionElementsForTaxon = CdmSpringContextHelper.getDescriptionService().listDescriptionElementsForTaxon(taxon, setFeature, null, null, null, DESCRIPTION_INIT_STRATEGY);
184
        sort(listDescriptionElementsForTaxon);
185
        return listDescriptionElementsForTaxon;
186
    }
187

    
188
    /**
189
     * Returns the list of {@link NamedArea}s for which the distribution status can't be updated.
190
     * @return List of {@link NamedArea}s for which the distribution status can't be updated.
191
     */
192
    public List<NamedArea> getReadOnlyAreas(){
193
        List<NamedArea> readonly = new ArrayList<>();
194
        // TODO: HACK FOR RL 2017: Remove as soon as possible by receiving read only areas from cdm preferences
195
        readonly.add(this.getAreaFromString("Deutschland"));
196
        return readonly;
197
    }
198

    
199
    /**
200
     * Returns the {@link NamedArea} referred to by the given {@code areaString}.
201
     * @param areaString An string referring to a {@link NamedArea}.
202
     * @return The {@link NamedArea} referred to by the given {@code areaString}.
203
     */
204
    public NamedArea getAreaFromString(String areaString){
205
        List<NamedArea> namedAreas = getChosenAreas();
206
        NamedArea area = null;
207
        for(NamedArea namedArea:namedAreas){
208
            Representation representation = namedArea.getRepresentation(Language.DEFAULT());
209
            if(representation!=null){
210
                if(DistributionEditorUtil.isAbbreviatedLabels()){
211
                    String label = representation.getLabel();
212
                    String abbreviatedLabel = representation.getAbbreviatedLabel();
213
                    if(abbreviatedLabel!=null && abbreviatedLabel.equalsIgnoreCase(areaString)){
214
                        area = namedArea;
215
                        break;
216
                    }
217
                    else if(label!=null && label.equalsIgnoreCase(areaString)){
218
                        area = namedArea;
219
                        break;
220
                    }
221
                }
222
            }
223
            if(namedArea.getTitleCache().equalsIgnoreCase(areaString)){
224
                area = namedArea;
225
                break;
226
            }
227
        }
228
        return area;
229
    }
230

    
231
    /**
232
     * Returns the {@link Distribution} of the given {@link Taxon}. 
233
     * @param taxon Taxon to get the {@link Distribution} of.
234
     * @return {@link Distribution} of the given {@link Taxon}.
235
     */
236
    private List<Distribution> getDistributions(Taxon taxon) {
237
        Set<Feature> setFeature = new HashSet<>(Arrays.asList(Feature.DISTRIBUTION()));
238
        List<Distribution> listTaxonDescription = CdmSpringContextHelper.getDescriptionService()
239
                .listDescriptionElementsForTaxon(taxon, setFeature, null, null, null, DESCRIPTION_INIT_STRATEGY);
240
        return listTaxonDescription;
241

    
242
    }
243

    
244
    /**
245
     * Returns the list of chosen {@link NamedArea}s defined in the 
246
     * related vaadin session attribute {@link DistributionEditorUtil#SATTR_SELECTED_AREAS}.
247
     * If this vaadin session attribute is not set, all allowed {@link NamedArea}s of the 
248
     * chosen {@link TermVocabulary} defined by the vaadin session attribute
249
     * {@link DistributionEditorUtil#SATTR_SELECTED_AREA_VOCABULARY_UUID} are returned.
250
     * @return List of chosen {@link NamedArea}s defined in the 
251
     * related vaadin session attribute {@link DistributionEditorUtil#SATTR_SELECTED_AREAS}.
252
     * If this vaadin session attribute is not set, all allowed {@link NamedArea}s of the 
253
     * chosen {@link TermVocabulary} defined by the vaadin session attribute
254
     * {@link DistributionEditorUtil#SATTR_SELECTED_AREA_VOCABULARY_UUID}.
255
     */
256
	private List<NamedArea> getChosenAreas(){
257
	    List<NamedArea> namedAreas = (List<NamedArea>)VaadinSession.getCurrent().getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREAS);
258
	    if(namedAreas!=null && namedAreas.isEmpty()){
259
	        return getChosenAreasFromVoc();
260
	    }
261
	    return namedAreas;
262
	}
263

    
264
	/**
265
	 * Returns all {@link NamedArea}s of the {@link TermVocabulary} defined 
266
	 * by the vaadin session attribute {@link DistributionEditorUtil#SATTR_SELECTED_AREA_VOCABULARY_UUID}
267
	 * ordered by labels.
268
	 * @return all {@link NamedArea}s of the {@link TermVocabulary} defined 
269
	 * by the vaadin session attribute {@link DistributionEditorUtil#SATTR_SELECTED_AREA_VOCABULARY_UUID}
270
	 * ordered by labels..
271
	 */
272
	private List<NamedArea> getChosenAreasFromVoc(){
273
	    VaadinSession session = VaadinSession.getCurrent();
274
	    UUID vocUUID = (UUID) session.getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREA_VOCABULARY_UUID);
275
	    TermVocabulary<NamedArea> vocabulary = CdmSpringContextHelper.getVocabularyService().load(vocUUID, Arrays.asList("terms")); //$NON-NLS-1$
276
	    vocabulary = CdmBase.deproxy(vocabulary, TermVocabulary.class);
277
	    if (vocabulary instanceof OrderedTermVocabulary) {
278
	        List<NamedArea> list = new ArrayList<> (((OrderedTermVocabulary)vocabulary).getOrderedTerms());
279
	        Collections.reverse(list);
280
	        return list;
281
	    }else {
282
	        return vocabulary.getTermsOrderedByLabels(Language.DEFAULT()).stream().collect(Collectors.toCollection(ArrayList::new));
283
	    }
284

    
285
	}
286

    
287
	/**
288
	 * Returns all {@link TaxonNode}s defined by the 
289
	 * vaadin session attribute {@link DistributionEditorUtil#SATTR_TAXON_NODES_UUID}.
290
	 * If this session attribute is not set, all {@link TaxonNode}s of the chosen
291
	 * classification defined by the vaadin session attribute 
292
	 * {@link DistributionEditorUtil#SATTR_CLASSIFICATION} are returned.
293
	 * @return All {@link TaxonNode}s defined by the 
294
	 * vaadin session attribute {@link DistributionEditorUtil#SATTR_TAXON_NODES_UUID}.
295
	 * If this session attribute is not set, all {@link TaxonNode}s of the chosen
296
	 * classification defined by the vaadin session attribute 
297
	 * {@link DistributionEditorUtil#SATTR_CLASSIFICATION}.
298
	 */
299
	private List<TaxonNode> getChosenTaxonNodes() {
300
		VaadinSession session = VaadinSession.getCurrent();
301
        List<UUID> taxonNodeUUIDs = (List<UUID>) session.getAttribute(DistributionEditorUtil.SATTR_TAXON_NODES_UUID);
302
        UUID classificationUuid = (UUID)session.getAttribute(DistributionEditorUtil.SATTR_CLASSIFICATION);
303
        if((taxonNodeUUIDs==null || taxonNodeUUIDs.isEmpty()) && classificationUuid!=null){
304
            Classification classification = CdmSpringContextHelper.getClassificationService().load(classificationUuid);
305
            if(classification!=null){
306
                taxonNodeUUIDs = Collections.singletonList(classification.getRootNode().getUuid());
307
            }
308
        }
309
        List<TaxonNode> loadedNodes = CdmSpringContextHelper.getTaxonNodeService().load(taxonNodeUUIDs, null);
310
        if(loadedNodes!=null){
311
            return loadedNodes;
312
        }
313
        return Collections.emptyList();
314
    }
315

    
316
	/**
317
	 * Returns the list of chosen {@link TaxonNode}s returned by {@link #getChosenTaxonNodes()}
318
	 * and adds their children to it.
319
	 * @return List of chosen {@link TaxonNode}s returned by {@link #getChosenTaxonNodes()}
320
	 * and their children.
321
	 */
322
	private List<TaxonNode> getAllNodes(){
323
		List<TaxonNode> allNodes = new ArrayList<>();
324

    
325
		List<TaxonNode> taxonNodes = getChosenTaxonNodes();
326
		for (TaxonNode taxonNode : taxonNodes) {
327
			if(taxonNode.getTaxon()!=null){
328
				allNodes.add(taxonNode);
329
			}
330
			allNodes.addAll(CdmSpringContextHelper.getTaxonNodeService().loadChildNodesOfTaxonNode(taxonNode, null, true, null));
331
		}
332
		return allNodes;
333
	}
334

    
335
	protected static final List<String> DESCRIPTION_INIT_STRATEGY = Arrays.asList(new String []{
336
            "$", //$NON-NLS-1$
337
"elements.*", //$NON-NLS-1$
338
"elements.sources.citation.authorship.$", //$NON-NLS-1$
339
"elements.sources.nameUsedInSource.originalNameString", //$NON-NLS-1$
340
"elements.area.level", //$NON-NLS-1$
341
"elements.modifyingText", //$NON-NLS-1$
342
"elements.states.*", //$NON-NLS-1$
343
"elements.media", //$NON-NLS-1$
344
"elements.multilanguageText", //$NON-NLS-1$
345
"multilanguageText", //$NON-NLS-1$
346
"stateData.$", //$NON-NLS-1$
347
"annotations", //$NON-NLS-1$
348
"markers", //$NON-NLS-1$
349
"sources.citation.authorship", //$NON-NLS-1$
350
"sources.nameUsedInSource", //$NON-NLS-1$
351
"multilanguageText", //$NON-NLS-1$
352
"media", //$NON-NLS-1$
353
"name.$", //$NON-NLS-1$
354
"name.rank", //$NON-NLS-1$
355
"name.status.type", //$NON-NLS-1$
356
"taxon2.name", //$NON-NLS-1$
357
});
358

    
359
/**Helper Methods*/
360
private void sort(List<DescriptionElementBase> list){
361
	Collections.sort(list, new Comparator<DescriptionElementBase>() {
362

    
363
		@Override
364
		public int compare(DescriptionElementBase o1, DescriptionElementBase o2) {
365
			String feature1 = o1.getFeature().getTitleCache();
366
			String feature2 = o2.getFeature().getTitleCache();
367
			if(feature1 !=null && feature2 !=null){
368
				return feature1.compareTo(feature2);
369
			}else{
370
				return 0;
371

    
372
			}
373
		}
374
	});
375
}
376

    
377
/**
378
 *
379
 * {@inheritDoc}
380
 */
381
@Override
382
protected void onPresenterReady() {
383
    /*
384
 * The area and taxon settings window should only be displayed after login
385
 * and only when no classification and areas are chosen yet.
386
 */
387
    VaadinSession vaadinSession = VaadinSession.getCurrent();
388
    if(userHelper.userIsAutheticated()
389
            && !userHelper.userIsAnnonymous()
390
            && (vaadinSession.getAttribute(DistributionEditorUtil.SATTR_CLASSIFICATION) == null
391
            || vaadinSession.getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREA_VOCABULARY_UUID) == null
392
            || vaadinSession.getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREAS) == null)) {
393
        getView().openAreaAndTaxonSettings();
394
    }
395
}
396

    
397
/**Unused Methods*/
398
// TODO: Currently unused. Remove?
399
private List<String> getAbbreviatedNamedAreas() {
400
    List<NamedArea> terms = getChosenAreasFromVoc();
401
    List<String> list = new ArrayList<>();
402
    for(DefinedTermBase<?> dtb: terms){
403
        for(Representation r : dtb.getRepresentations()){
404
            list.add(r.getAbbreviatedLabel());
405
        }
406
    }
407
    return list;
408
}
409

    
410
// TODO: Currently unused. Remove?
411
private HashMap<DescriptionElementBase, Distribution> getDistribution(DefinedTermBase dt, Taxon taxon) {
412
    Set<Feature> setFeature = new HashSet<>(Arrays.asList(Feature.DISTRIBUTION()));
413
    List<DescriptionElementBase> listTaxonDescription = CdmSpringContextHelper.getDescriptionService().listDescriptionElementsForTaxon(taxon, setFeature, null, null, null, DESCRIPTION_INIT_STRATEGY);
414
    HashMap<DescriptionElementBase, Distribution> map = null;
415
    for(DescriptionElementBase deb : listTaxonDescription){
416
        if(deb instanceof Distribution){
417
            Distribution db = (Distribution)deb;
418
            String titleCache = dt.getTitleCache();
419
            if(db.getArea().getTitleCache().equalsIgnoreCase(titleCache)){
420
                map = new HashMap<DescriptionElementBase, Distribution>();
421
                map.put(deb, db);
422
            }
423
        }
424
    }
425
    return map;
426
}
427

    
428
public LazyQueryContainer getAreaDistributionStatusContainer() {
429
    List<UUID> nodeUuids = getAllNodes().stream().map(n -> n.getUuid()).collect(Collectors.toCollection(ArrayList::new));
430
    List<NamedArea> namedAreas = getChosenAreas();
431
    if(namedAreas!=null){
432
        QueryFactory factory = new DistributionStatusQueryFactory(this.repo, nodeUuids, namedAreas);
433
        QueryDefinition defintion = new DistributionStatusQueryDefinition(namedAreas, true, 50);
434
        return new LazyQueryContainer(defintion, factory);
435
    }
436
    return null;
437
}
438
}
(1-1/4)