Project

General

Profile

Download (17.6 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.TaxonNodeDto;
50
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
51
import eu.etaxonomy.cdm.vaadin.container.CdmSQLContainer;
52
import eu.etaxonomy.cdm.vaadin.container.NamedAreaContainer;
53
import eu.etaxonomy.cdm.vaadin.container.TaxonNodeContainer;
54
import eu.etaxonomy.cdm.vaadin.util.CdmQueryFactory;
55
import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
56
import eu.etaxonomy.cdm.vaadin.util.DistributionEditorUtil;
57
import eu.etaxonomy.cdm.vaadin.view.distributionStatus.IDistributionTableView;
58
import eu.etaxonomy.cdm.vaadin.view.distributionStatus.settings.AreaAndTaxonSettingsPresenter;
59

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

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

    
81
    /**
82
     * The constructor should first build the main layout, set the
83
     * composition root and then do any custom initialization.
84
     *
85
     * The constructor will not be automatically regenerated by the
86
     * visual editor.
87
     * @param distributionTableView
88
     */
89
    public AreaAndTaxonSettingsConfigWindow(IDistributionTableView distributionTableView) {
90
        super();
91
        this.distributionTableView = distributionTableView;
92
    }
93

    
94
    /**
95
     *
96
     * {@inheritDoc}
97
     */
98
    @Override
99
    protected void init() {
100
        //init classification
101
        Classification classification = presenter.getChosenClassification();
102
        try {
103
            CdmSQLContainer classificationContainer = new CdmSQLContainer(CdmQueryFactory.generateTableQuery("Classification")); //$NON-NLS-1$
104
            classificationContainer.sort(new Object[] {"titleCache"}, new boolean[] {true}); //$NON-NLS-1$
105
            classificationBox.setContainerDataSource(classificationContainer);
106
        } catch (SQLException e) {
107
            DistributionEditorUtil.showSqlError(e);
108
        }
109
        RowId classificationRow = null;
110
        if(classification!=null){
111
            classificationRow = new RowId(classification.getId());
112
            TaxonNode root = CdmSpringContextHelper.getClassificationService().getRootNode(classification.getUuid());
113
            showClassificationTaxa(root);
114
        }
115
        else if(classificationBox.getItemIds().size()==1){
116
            //only one classification exists
117
            classificationRow = (RowId) classificationBox.getItemIds().iterator().next();
118
        }
119
        if(classificationRow!=null){
120
            classificationBox.setValue(classificationRow);
121
        }
122

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

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

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

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

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

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

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

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

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

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

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

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

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

    
208

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

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

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

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

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

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

    
243
        return leftAndRightContainer;
244
    }
245

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

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

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

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

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

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

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

    
382

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

    
391
    /**
392
     * Thread to populate {@link AreaAndTaxonSettingsConfigWindow#taxonTree}.
393
     *
394
     */
395
    private class TreeUpdater extends Thread{
396

    
397
    	/**
398
    	 * The taxa to show.
399
    	 */
400
    	private Collection<TaxonNodeDto> children;
401

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

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

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

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

    
439
}
(1-1/6)