Project

General

Profile

Download (17.7 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2015 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.component.distributionStatus;
10

    
11
import java.sql.SQLException;
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.UUID;
17

    
18
import com.vaadin.data.Container;
19
import com.vaadin.data.Property;
20
import com.vaadin.data.Property.ValueChangeEvent;
21
import com.vaadin.data.Property.ValueChangeListener;
22
import com.vaadin.data.util.BeanItemContainer;
23
import com.vaadin.data.util.sqlcontainer.RowId;
24
import com.vaadin.server.Page;
25
import com.vaadin.server.VaadinSession;
26
import com.vaadin.ui.AbstractLayout;
27
import com.vaadin.ui.Alignment;
28
import com.vaadin.ui.Button.ClickEvent;
29
import com.vaadin.ui.Button.ClickListener;
30
import com.vaadin.ui.ComboBox;
31
import com.vaadin.ui.HorizontalLayout;
32
import com.vaadin.ui.Notification;
33
import com.vaadin.ui.OptionGroup;
34
import com.vaadin.ui.Panel;
35
import com.vaadin.ui.Table.ColumnHeaderMode;
36
import com.vaadin.ui.TextField;
37
import com.vaadin.ui.Tree.ExpandEvent;
38
import com.vaadin.ui.Tree.ExpandListener;
39
import com.vaadin.ui.TreeTable;
40
import com.vaadin.ui.UI;
41
import com.vaadin.ui.VerticalLayout;
42

    
43
import eu.etaxonomy.cdm.common.CdmUtils;
44
import eu.etaxonomy.cdm.i18n.Messages;
45
import eu.etaxonomy.cdm.model.location.NamedArea;
46
import eu.etaxonomy.cdm.model.taxon.Classification;
47
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
48
import eu.etaxonomy.cdm.model.term.TermVocabulary;
49
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
50
import eu.etaxonomy.cdm.vaadin.container.CdmSQLContainer;
51
import eu.etaxonomy.cdm.vaadin.container.NamedAreaContainer;
52
import eu.etaxonomy.cdm.vaadin.container.TaxonNodeContainer;
53
import eu.etaxonomy.cdm.vaadin.util.CdmQueryFactory;
54
import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
55
import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
56
import eu.etaxonomy.cdm.vaadin.view.distributionStatus.IDistributionTableView;
57
import eu.etaxonomy.cdm.vaadin.view.distributionStatus.settings.AreaAndTaxonSettingsPresenter;
58

    
59
/**
60
 *
61
 * @author pplitzner
62
 * A Configuration window for choosing distribution areas and taxa to work with.
63
 *
64
 */
65
public class AreaAndTaxonSettingsConfigWindow
66
            extends SettingsDialogWindowBase<AreaAndTaxonSettingsPresenter>
67
            implements ValueChangeListener, ClickListener, ExpandListener{
68

    
69
	/**
70
	 * 
71
	 */
72
    private static final long serialVersionUID = 1439411115014088780L;
73
    private ComboBox classificationBox;
74
    private TextField taxonFilter;
75
    private ComboBox distAreaBox;
76
    private OptionGroup namedAreaList;
77
    private TreeTable taxonTree;
78
    private IDistributionTableView distributionTableView;
79

    
80
    /**
81
     * The constructor should first build the main layout, set the
82
     * composition root and then do any custom initialization.
83
     *
84
     * The constructor will not be automatically regenerated by the
85
     * visual editor.
86
     * @param distributionTableView
87
     */
88
    public AreaAndTaxonSettingsConfigWindow(IDistributionTableView distributionTableView) {
89
        super();
90
        this.distributionTableView = distributionTableView;
91
    }
92
    
93
    /**
94
     * 
95
     * {@inheritDoc}
96
     */
97
    @Override
98
    protected void init() {
99
        //init classification
100
        Classification classification = presenter.getChosenClassification();
101
        try {
102
            CdmSQLContainer classificationContainer = new CdmSQLContainer(CdmQueryFactory.generateTableQuery("Classification")); //$NON-NLS-1$
103
            classificationContainer.sort(new Object[] {"titleCache"}, new boolean[] {true}); //$NON-NLS-1$
104
            classificationBox.setContainerDataSource(classificationContainer);
105
        } catch (SQLException e) {
106
            DistributionEditorUtil.showSqlError(e);
107
        }
108
        RowId classificationRow = null;
109
        if(classification!=null){
110
            classificationRow = new RowId(classification.getId());
111
            TaxonNode root = CdmSpringContextHelper.getClassificationService().getRootNode(classification.getUuid());
112
            showClassificationTaxa(root);
113
        }
114
        else if(classificationBox.getItemIds().size()==1){
115
            //only one classification exists
116
            classificationRow = (RowId) classificationBox.getItemIds().iterator().next();
117
        }
118
        if(classificationRow!=null){
119
            classificationBox.setValue(classificationRow);
120
        }
121

    
122
        classificationBox.addValueChangeListener(this);
123
        taxonFilter.addValueChangeListener(this);
124
        taxonTree.addExpandListener(this);
125

    
126
        //init areas
127
        TermVocabulary<NamedArea> chosenAreaVoc = presenter.getChosenAreaVoc();
128
        Container areaVocContainer = presenter.getAreaContainer();
129
        if (areaVocContainer.size() == 1){
130
            chosenAreaVoc = (TermVocabulary<NamedArea>)areaVocContainer.getItemIds().iterator().next();
131
        }
132
        distAreaBox.setContainerDataSource(areaVocContainer);
133
        distAreaBox.setValue(chosenAreaVoc);
134
        distAreaBox.addValueChangeListener(this);
135

    
136
        if(chosenAreaVoc!=null){
137
            NamedAreaContainer areaContainer = new NamedAreaContainer(chosenAreaVoc);
138
            namedAreaList.setContainerDataSource(areaContainer);
139
        }
140
        Object selectedAreas = VaadinSession.getCurrent().getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREAS);
141
        namedAreaList.setValue(selectedAreas);
142

    
143
        okButton.addClickListener(this);
144
        cancelButton.addClickListener(this);
145
        updateButtons();
146
    }
147

    
148
    /**
149
     * 
150
     * {@inheritDoc}
151
     */
152
    @Override
153
    protected AbstractLayout buildMainLayout() {
154

    
155
        mainLayout = new VerticalLayout();
156
        mainLayout.setSizeFull();
157

    
158
        HorizontalLayout leftAndRightContainer = new HorizontalLayout();
159
        leftAndRightContainer.setImmediate(false);
160
        leftAndRightContainer.setSizeFull();
161
        leftAndRightContainer.setMargin(true);
162
        leftAndRightContainer.setSpacing(true);
163

    
164
        VerticalLayout leftContainer = new VerticalLayout();
165
        leftContainer.setImmediate(false);
166
        leftContainer.setSpacing(true);
167
        leftContainer.setSizeFull();
168

    
169
        VerticalLayout rightContainer = new VerticalLayout();
170
        rightContainer.setImmediate(false);
171
        rightContainer.setSpacing(true);
172
        rightContainer.setSizeFull();
173

    
174
        //classification
175
        classificationBox = new ComboBox(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_CLASSIFICATION));
176
        classificationBox.setItemCaptionPropertyId(TaxonNodeContainer.LABEL);
177
        classificationBox.setInputPrompt(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_SELECT_CLASSIFICATION));
178
        classificationBox.setImmediate(true);
179
        classificationBox.setNewItemsAllowed(false);
180
        classificationBox.setNullSelectionAllowed(false);
181
        classificationBox.setSizeFull();
182
        classificationBox.setWidth("100%"); //$NON-NLS-1$
183

    
184
        //taxonFilter
185
        taxonFilter = new TextField(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_FILTER));
186
        taxonFilter.setInputPrompt(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_FILTER_TAXA_BY_NAME));
187
        taxonFilter.setSizeFull();
188
        taxonFilter.setImmediate(true);
189

    
190
        //distribution area box
191
        distAreaBox = new ComboBox(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_DISTRIBUTION_AREA));
192
        distAreaBox.setInputPrompt(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_SELECT_DISTRIBUTION_AREA));
193
        distAreaBox.setImmediate(true);
194
        distAreaBox.setNullSelectionAllowed(false);
195
        distAreaBox.setNewItemsAllowed(false);
196
        distAreaBox.setSizeFull();
197
        distAreaBox.setWidth("100%"); //$NON-NLS-1$
198

    
199
        // named areas
200
        namedAreaList = new OptionGroup();
201
        namedAreaList.setMultiSelect(true);
202
        namedAreaList.setSizeFull();
203
        Panel namedAreaPanel = new Panel(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_AREAS));
204
        namedAreaPanel.setContent(new VerticalLayout(namedAreaList));
205
        namedAreaPanel.setSizeFull();
206

    
207

    
208
        //taxonomy
209
        taxonTree = new TreeTable(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_TAXONOMY));
210
        taxonTree.setSelectable(true);
211
        taxonTree.setSizeFull();
212
        taxonTree.setImmediate(true);
213
        taxonTree.setCacheRate(20);
214
        taxonTree.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
215
        taxonTree.setMultiSelect(true);
216

    
217
        leftContainer.addComponent(distAreaBox);
218
        leftContainer.addComponent(namedAreaPanel);
219
        leftContainer.setExpandRatio(distAreaBox, 0.1f);
220
        leftContainer.setExpandRatio(namedAreaPanel, 0.9f);
221
        leftContainer.setSizeFull();
222

    
223
        rightContainer.addComponent(classificationBox);
224
        rightContainer.addComponent(taxonFilter);
225
        rightContainer.addComponent(taxonTree);
226
        rightContainer.setExpandRatio(classificationBox, 0.1f);
227
        rightContainer.setExpandRatio(taxonFilter, 0.1f);
228
        rightContainer.setExpandRatio(taxonTree, 0.8f);
229

    
230
        leftAndRightContainer.addComponent(leftContainer);
231
        leftAndRightContainer.addComponent(rightContainer);
232

    
233
        //button toolbar
234
        HorizontalLayout buttonToolBar = createOkCancelButtons();
235

    
236
        mainLayout.addComponent(leftAndRightContainer);
237
        mainLayout.addComponent(buttonToolBar);
238
        mainLayout.setExpandRatio(leftAndRightContainer, 0.9f);
239
        mainLayout.setExpandRatio(buttonToolBar, 0.1f);
240
        mainLayout.setComponentAlignment(buttonToolBar, Alignment.BOTTOM_RIGHT);
241

    
242
        return leftAndRightContainer;
243
    }
244

    
245
    /**
246
     * 
247
     * {@inheritDoc}
248
     */
249
    @Override
250
    public void valueChange(ValueChangeEvent event) {
251
        Property<?> property = event.getProperty();
252
        if(property==classificationBox){
253
        	UuidAndTitleCache<TaxonNode> parent = getUuidAndTitleCacheFromRowId(classificationBox.getValue());
254
        	TaxonNode root = CdmSpringContextHelper.getClassificationService().getRootNode(parent.getUuid());
255
        	showClassificationTaxa(root);
256
        }
257
        else if(property==taxonFilter){
258
            String filterText = taxonFilter.getValue();
259
            Property<?> uuidProperty = classificationBox.getContainerProperty(classificationBox.getValue(),"uuid"); //$NON-NLS-1$
260
            if(uuidProperty==null){
261
            	Notification.show(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_SELECT_CLASSIFICATION));
262
            }
263
            else{
264
            	if(CdmUtils.isNotBlank(filterText)){
265
            		UUID classificationUuid = UUID.fromString((String) uuidProperty.getValue());
266
            		List<UuidAndTitleCache<TaxonNode>> taxa = CdmSpringContextHelper.getTaxonNodeService().getUuidAndTitleCache(null, filterText, classificationUuid);
267
            		BeanItemContainer<UuidAndTitleCache<TaxonNode>> container = new BeanItemContainer<>(UuidAndTitleCache.class);
268
            		taxonTree.setContainerDataSource(container);
269
            		for (UuidAndTitleCache<TaxonNode> taxon : taxa) {
270
            			container.addItem(taxon);
271
            			taxonTree.setChildrenAllowed(taxon, false);
272
            		}
273
            		taxonTree.setVisibleColumns("titleCache"); //$NON-NLS-1$
274
            	}
275
            	else{
276
            		UuidAndTitleCache<TaxonNode> parent = getUuidAndTitleCacheFromRowId(classificationBox.getValue());
277
            		TaxonNode root = CdmSpringContextHelper.getClassificationService().getRootNode(parent.getUuid());
278
            		showClassificationTaxa(root);
279
            	}
280
            }
281
        }
282
        else if(property==distAreaBox){
283
            TermVocabulary<NamedArea> vocabulary = (TermVocabulary<NamedArea>) event.getProperty().getValue();
284
            NamedAreaContainer container = new NamedAreaContainer(vocabulary);
285
            namedAreaList.setContainerDataSource(container);
286
        }
287
        updateButtons();
288
    }
289

    
290
    /**
291
     * 
292
     * {@inheritDoc}
293
     */
294
    @Override
295
    protected boolean isValid() {
296
        return classificationBox.getValue()!=null && distAreaBox.getValue()!=null;
297
    }
298

    
299
    /**
300
     * 
301
     * {@inheritDoc}
302
     */
303
    @Override
304
    public void buttonClick(ClickEvent event) {
305
        Object source = event.getSource();
306
        if(source==okButton){
307
            List<UUID> taxonNodes = new ArrayList<>();
308
            TermVocabulary<NamedArea> areaVoc = null;
309
            String uuidString = (String) classificationBox.getContainerProperty(classificationBox.getValue(),"uuid").getValue(); //$NON-NLS-1$
310
            UUID classificationUuid = UUID.fromString(uuidString);
311
            Set<UuidAndTitleCache<TaxonNode>> treeSelection = (Set<UuidAndTitleCache<TaxonNode>>) taxonTree.getValue();
312
			if(!treeSelection.isEmpty()){
313
				for (UuidAndTitleCache<TaxonNode> uuidAndTitleCache : treeSelection) {
314
					taxonNodes.add(uuidAndTitleCache.getUuid());
315
				}
316
            }
317
			if(treeSelection.isEmpty() && CdmUtils.isNotBlank(taxonFilter.getValue())) {
318
                for (UuidAndTitleCache<TaxonNode> uuidAndTitleCache : (Collection<UuidAndTitleCache<TaxonNode>>) taxonTree.getItemIds()) {
319
                    taxonNodes.add(uuidAndTitleCache.getUuid());
320
                }
321
			}
322
            areaVoc = (TermVocabulary<NamedArea>) distAreaBox.getValue();
323
            List<NamedArea> selectedAreas = new ArrayList<>((Set<NamedArea>)namedAreaList.getValue()); //getValue is LinkedHashSet and therefore sorted
324
            DistributionEditorUtil.updateDistributionView(distributionTableView, taxonNodes, areaVoc, selectedAreas, classificationUuid);
325
            window.close();
326
        }
327
        else if(source==cancelButton){
328
            window.close();
329
        }
330
    }
331

    
332
    /**
333
     * 
334
     * {@inheritDoc}
335
     */
336
    @Override
337
    public void nodeExpand(ExpandEvent event) {
338
        UuidAndTitleCache<TaxonNode> parent = (UuidAndTitleCache<TaxonNode>) event.getItemId();
339
        ((TaxonNodeContainer) taxonTree.getContainerDataSource()).addChildItems(parent);
340
    }
341

    
342
    /**
343
     * Starts a {@link TreeUpdater} thread to populate the {@link #taxonTree} with taxa of the classification specified by the given {@code rootNode}.
344
     * @param rootNode The root node of the classification whose taxa should be shown in the {@link #taxonTree}.
345
     */
346
    private void showClassificationTaxa(TaxonNode rootNode) {
347
        final Collection<UuidAndTitleCache<TaxonNode>> children = CdmSpringContextHelper.getTaxonNodeService().listChildNodesAsUuidAndTitleCache(rootNode);
348
        // Enable polling and set frequency to 0.5 seconds
349
        UI.getCurrent().setPollInterval(500);
350
        taxonTree.setEnabled(false);
351
        taxonTree.removeAllItems();
352
        Notification.show(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_LOADING_TAXA));
353
        new TreeUpdater(children).start();
354
    }
355

    
356
    /**
357
     * Returns the {@link UuidAndTitleCache} object of the classification specified by the given {@link RowId} of the {@link CdmSQLContainer} used in the {@link #classificationBox}.
358
     * @param classificationSelection
359
     * @return {@link UuidAndTitleCache} object of the given classification specified by {@code classificationSelection}
360
     */
361
    private UuidAndTitleCache<TaxonNode> getUuidAndTitleCacheFromRowId(Object classificationSelection) {
362
        String uuidString = (String) classificationBox.getContainerProperty(classificationSelection, "uuid").getValue(); //$NON-NLS-1$
363
        Property<Integer> rootNodeContainerProperty = null;
364

    
365
        Collection<?> ids = classificationBox.getContainerPropertyIds();
366
        //use for loop here because the case of the root node id columns differs between some DBs
367
        for (Object id : ids) {
368
			if(id instanceof String && ((String) id).toLowerCase().equals("rootnode_id")){ //$NON-NLS-1$
369
				rootNodeContainerProperty = classificationBox.getContainerProperty(classificationSelection, id);
370
				break;
371
			}
372
		}
373
		int id = rootNodeContainerProperty.getValue();
374
        String titleCache = (String) classificationBox.getContainerProperty(classificationSelection, "titleCache").getValue(); //$NON-NLS-1$
375
        UUID uuid = UUID.fromString(uuidString);
376
        UuidAndTitleCache<TaxonNode> parent = new UuidAndTitleCache<>(uuid, id, titleCache);
377
        return parent;
378
    }
379

    
380

    
381
    /**
382
     * {@inheritDoc}
383
     */
384
    @Override
385
    protected AreaAndTaxonSettingsPresenter getPresenter() {
386
        return new AreaAndTaxonSettingsPresenter();
387
    }
388

    
389
    /**
390
     * Thread to populate {@link AreaAndTaxonSettingsConfigWindow#taxonTree}.
391
     *
392
     */
393
    private class TreeUpdater extends Thread{
394
    
395
    	/**
396
    	 * The taxa to show.
397
    	 */
398
    	private Collection<UuidAndTitleCache<TaxonNode>> children;
399

    
400
    	/**
401
    	 * Creates a thread to show the given collection of taxa in {@link AreaAndTaxonSettingsConfigWindow#taxonTree}.
402
    	 * @param children {@link UuidAndTitleCache} of the taxa to show.
403
    	 */
404
		public TreeUpdater(Collection<UuidAndTitleCache<TaxonNode>> children) {
405
			this.children = children;
406
		}
407

    
408
		/**
409
		 * 
410
		 * {@inheritDoc}
411
		 */
412
		@Override
413
    	public void run() {
414
			UI.getCurrent().access(new Runnable() {
415
				/**
416
				 * 
417
				 * {@inheritDoc}
418
				 */
419
				@Override
420
				public void run() {
421
					taxonTree.setContainerDataSource(new TaxonNodeContainer(children));
422

    
423
			        Notification notification = new Notification(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_LOADING_COMPLETE));
424
			        notification.setDelayMsec(500);
425
			        notification.show(Page.getCurrent());
426
			        taxonTree.setEnabled(true);
427
			        taxonTree.setSortContainerPropertyId("titleCache"); //$NON-NLS-1$
428
			        taxonTree.sort();
429

    
430
			        //disable polling when all taxa are loaded
431
			        UI.getCurrent().setPollInterval(-1);
432
				}
433
			});
434
    	}
435
    }
436

    
437
}
(1-1/6)