2 * Copyright (C) 2015 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.vaadin
.view
.distributionStatus
;
11 import java
.sql
.SQLException
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.List
;
16 import java
.util
.UUID
;
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
.ListSelect
;
33 import com
.vaadin
.ui
.Notification
;
34 import com
.vaadin
.ui
.Table
.ColumnHeaderMode
;
35 import com
.vaadin
.ui
.TextField
;
36 import com
.vaadin
.ui
.Tree
.ExpandEvent
;
37 import com
.vaadin
.ui
.Tree
.ExpandListener
;
38 import com
.vaadin
.ui
.TreeTable
;
39 import com
.vaadin
.ui
.UI
;
40 import com
.vaadin
.ui
.VerticalLayout
;
42 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
43 import eu
.etaxonomy
.cdm
.i18n
.Messages
;
44 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
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
.persistence
.dto
.UuidAndTitleCache
;
49 import eu
.etaxonomy
.cdm
.vaadin
.container
.CdmSQLContainer
;
50 import eu
.etaxonomy
.cdm
.vaadin
.container
.NamedAreaContainer
;
51 import eu
.etaxonomy
.cdm
.vaadin
.container
.TaxonNodeContainer
;
52 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmQueryFactory
;
53 import eu
.etaxonomy
.cdm
.vaadin
.util
.CdmSpringContextHelper
;
54 import eu
.etaxonomy
.cdm
.vaadin
.util
.DistributionEditorUtil
;
55 import eu
.etaxonomy
.cdm
.vaadin
.view
.distributionStatus
.settings
.AreaAndTaxonSettingsPresenter
;
62 public class AreaAndTaxonSettingsConfigWindow
63 extends SettingsDialogWindowBase
<AreaAndTaxonSettingsPresenter
>
64 implements ValueChangeListener
, ClickListener
, ExpandListener
{
66 private static final long serialVersionUID
= 1439411115014088780L;
67 private ComboBox classificationBox
;
68 private TextField taxonFilter
;
69 private ComboBox distAreaBox
;
70 private ListSelect namedAreaList
;
71 private TreeTable taxonTree
;
72 private IDistributionTableView distributionTableView
;
75 * The constructor should first build the main layout, set the
76 * composition root and then do any custom initialization.
78 * The constructor will not be automatically regenerated by the
80 * @param distributionTableView
82 public AreaAndTaxonSettingsConfigWindow(IDistributionTableView distributionTableView
) {
84 this.distributionTableView
= distributionTableView
;
88 protected void init() {
90 Classification classification
= presenter
.getChosenClassification();
92 CdmSQLContainer classificationContainer
= new CdmSQLContainer(CdmQueryFactory
.generateTableQuery("Classification")); //$NON-NLS-1$
93 classificationContainer
.sort(new Object
[] {"titleCache"}, new boolean[] {true}); //$NON-NLS-1$
94 classificationBox
.setContainerDataSource(classificationContainer
);
95 } catch (SQLException e
) {
96 DistributionEditorUtil
.showSqlError(e
);
98 RowId classificationRow
= null;
99 if(classification
!=null){
100 classificationRow
= new RowId(classification
.getId());
102 else if(classificationBox
.getItemIds().size()==1){
103 //only one classification exists
104 classificationRow
= (RowId
) classificationBox
.getItemIds().iterator().next();
106 if(classificationRow
!=null){
107 classificationBox
.setValue(classificationRow
);
108 showClassificationTaxa(getUuidAndTitleCacheFromRowId(classificationRow
));
111 classificationBox
.addValueChangeListener(this);
112 taxonFilter
.addValueChangeListener(this);
113 taxonTree
.addExpandListener(this);
116 TermVocabulary
<NamedArea
> chosenAreaVoc
= presenter
.getChosenAreaVoc();
117 Container areaVocContainer
= presenter
.getAreaContainer();
118 if (areaVocContainer
.size() == 1){
119 chosenAreaVoc
= (TermVocabulary
<NamedArea
>)areaVocContainer
.getItemIds().iterator().next();
121 distAreaBox
.setContainerDataSource(areaVocContainer
);
122 distAreaBox
.setValue(chosenAreaVoc
);
123 distAreaBox
.addValueChangeListener(this);
125 if(chosenAreaVoc
!=null){
126 NamedAreaContainer areaContainer
= new NamedAreaContainer(chosenAreaVoc
);
127 namedAreaList
.setContainerDataSource(areaContainer
);
129 Object selectedAreas
= VaadinSession
.getCurrent().getAttribute(DistributionEditorUtil
.SATTR_SELECTED_AREAS
);
130 namedAreaList
.setValue(selectedAreas
);
132 okButton
.addClickListener(this);
133 cancelButton
.addClickListener(this);
138 protected AbstractLayout
buildMainLayout() {
140 mainLayout
= new VerticalLayout();
141 mainLayout
.setSizeFull();
143 HorizontalLayout leftAndRightContainer
= new HorizontalLayout();
144 leftAndRightContainer
.setImmediate(false);
145 leftAndRightContainer
.setSizeFull();
146 leftAndRightContainer
.setMargin(true);
147 leftAndRightContainer
.setSpacing(true);
149 VerticalLayout leftContainer
= new VerticalLayout();
150 leftContainer
.setImmediate(false);
151 leftContainer
.setSpacing(true);
152 leftContainer
.setSizeFull();
154 VerticalLayout rightContainer
= new VerticalLayout();
155 rightContainer
.setImmediate(false);
156 rightContainer
.setSpacing(true);
157 rightContainer
.setSizeFull();
160 classificationBox
= new ComboBox(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_CLASSIFICATION
));
161 classificationBox
.setItemCaptionPropertyId(TaxonNodeContainer
.LABEL
);
162 classificationBox
.setInputPrompt(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_SELECT_CLASSIFICATION
));
163 classificationBox
.setImmediate(true);
164 classificationBox
.setNewItemsAllowed(false);
165 classificationBox
.setNullSelectionAllowed(false);
166 classificationBox
.setSizeFull();
167 classificationBox
.setWidth("100%"); //$NON-NLS-1$
170 taxonFilter
= new TextField(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_FILTER
));
171 taxonFilter
.setInputPrompt(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_FILTER_TAXA_BY_NAME
));
172 taxonFilter
.setSizeFull();
173 taxonFilter
.setImmediate(true);
175 //distribution area box
176 distAreaBox
= new ComboBox(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_DISTRIBUTION_AREA
));
177 distAreaBox
.setInputPrompt(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_SELECT_DISTRIBUTION_AREA
));
178 distAreaBox
.setImmediate(true);
179 distAreaBox
.setNullSelectionAllowed(false);
180 distAreaBox
.setNewItemsAllowed(false);
181 distAreaBox
.setSizeFull();
182 distAreaBox
.setWidth("100%"); //$NON-NLS-1$
185 namedAreaList
= new ListSelect();
186 namedAreaList
.setCaption(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_AREAS
));
187 namedAreaList
.setSizeFull();
188 namedAreaList
.setMultiSelect(true);
191 taxonTree
= new TreeTable(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_TAXONOMY
));
192 taxonTree
.setSelectable(true);
193 taxonTree
.setSizeFull();
194 taxonTree
.setImmediate(true);
195 taxonTree
.setCacheRate(20);
196 taxonTree
.setColumnHeaderMode(ColumnHeaderMode
.HIDDEN
);
197 taxonTree
.setMultiSelect(true);
199 leftContainer
.addComponent(distAreaBox
);
200 leftContainer
.addComponent(namedAreaList
);
201 leftContainer
.setExpandRatio(distAreaBox
, 0.1f
);
202 leftContainer
.setExpandRatio(namedAreaList
, 0.9f
);
203 leftContainer
.setSizeFull();
205 rightContainer
.addComponent(classificationBox
);
206 rightContainer
.addComponent(taxonFilter
);
207 rightContainer
.addComponent(taxonTree
);
208 rightContainer
.setExpandRatio(classificationBox
, 0.1f
);
209 rightContainer
.setExpandRatio(taxonFilter
, 0.1f
);
210 rightContainer
.setExpandRatio(taxonTree
, 0.8f
);
212 leftAndRightContainer
.addComponent(leftContainer
);
213 leftAndRightContainer
.addComponent(rightContainer
);
216 HorizontalLayout buttonToolBar
= createOkCancelButtons();
218 mainLayout
.addComponent(leftAndRightContainer
);
219 mainLayout
.addComponent(buttonToolBar
);
220 mainLayout
.setExpandRatio(leftAndRightContainer
, 0.9f
);
221 mainLayout
.setExpandRatio(buttonToolBar
, 0.1f
);
222 mainLayout
.setComponentAlignment(buttonToolBar
, Alignment
.BOTTOM_RIGHT
);
224 return leftAndRightContainer
;
228 public void valueChange(ValueChangeEvent event
) {
229 Property
<?
> property
= event
.getProperty();
230 if(property
==classificationBox
){
231 UuidAndTitleCache
<TaxonNode
> parent
= getUuidAndTitleCacheFromRowId(classificationBox
.getValue());
232 showClassificationTaxa(parent
);
234 else if(property
==taxonFilter
){
235 String filterText
= taxonFilter
.getValue();
236 Property
<?
> uuidProperty
= classificationBox
.getContainerProperty(classificationBox
.getValue(),"uuid"); //$NON-NLS-1$
237 if(uuidProperty
==null){
238 Notification
.show(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_SELECT_CLASSIFICATION
));
241 if(CdmUtils
.isNotBlank(filterText
)){
242 UUID classificationUuid
= UUID
.fromString((String
) uuidProperty
.getValue());
243 List
<UuidAndTitleCache
<TaxonNode
>> taxa
= CdmSpringContextHelper
.getTaxonNodeService().getUuidAndTitleCache(null, filterText
, classificationUuid
);
244 BeanItemContainer
<UuidAndTitleCache
<TaxonNode
>> container
= new BeanItemContainer
<>(UuidAndTitleCache
.class);
245 taxonTree
.setContainerDataSource(container
);
246 for (UuidAndTitleCache
<TaxonNode
> taxon
: taxa
) {
247 container
.addItem(taxon
);
248 taxonTree
.setChildrenAllowed(taxon
, false);
250 taxonTree
.setVisibleColumns("titleCache"); //$NON-NLS-1$
253 UuidAndTitleCache
<TaxonNode
> parent
= getUuidAndTitleCacheFromRowId(classificationBox
.getValue());
254 showClassificationTaxa(parent
);
258 else if(property
==distAreaBox
){
259 TermVocabulary
<NamedArea
> vocabulary
= (TermVocabulary
<NamedArea
>) event
.getProperty().getValue();
260 NamedAreaContainer container
= new NamedAreaContainer(vocabulary
);
261 namedAreaList
.setContainerDataSource(container
);
267 protected boolean isValid() {
268 return classificationBox
.getValue()!=null && distAreaBox
.getValue()!=null;
272 public void buttonClick(ClickEvent event
) {
273 Object source
= event
.getSource();
274 if(source
==okButton
){
275 List
<UUID
> taxonNodes
= new ArrayList
<>();
276 TermVocabulary
<NamedArea
> areaVoc
= null;
277 String uuidString
= (String
) classificationBox
.getContainerProperty(classificationBox
.getValue(),"uuid").getValue(); //$NON-NLS-1$
278 UUID classificationUuid
= UUID
.fromString(uuidString
);
279 Set
<UuidAndTitleCache
<TaxonNode
>> treeSelection
= (Set
<UuidAndTitleCache
<TaxonNode
>>) taxonTree
.getValue();
280 if(!treeSelection
.isEmpty()){
281 for (UuidAndTitleCache
<TaxonNode
> uuidAndTitleCache
: treeSelection
) {
282 taxonNodes
.add(uuidAndTitleCache
.getUuid());
285 if(treeSelection
.isEmpty() && CdmUtils
.isNotBlank(taxonFilter
.getValue())) {
286 for (UuidAndTitleCache
<TaxonNode
> uuidAndTitleCache
: (Collection
<UuidAndTitleCache
<TaxonNode
>>) taxonTree
.getItemIds()) {
287 taxonNodes
.add(uuidAndTitleCache
.getUuid());
290 areaVoc
= (TermVocabulary
<NamedArea
>) distAreaBox
.getValue();
291 List
<NamedArea
> selectedAreas
= new ArrayList
<>((Set
<NamedArea
>)namedAreaList
.getValue()); //getValue is LinkedHashSet and therefore sorted
292 DistributionEditorUtil
.updateDistributionView(distributionTableView
, taxonNodes
, areaVoc
, selectedAreas
, classificationUuid
);
295 else if(source
==cancelButton
){
301 public void nodeExpand(ExpandEvent event
) {
302 UuidAndTitleCache
<TaxonNode
> parent
= (UuidAndTitleCache
<TaxonNode
>) event
.getItemId();
303 ((TaxonNodeContainer
) taxonTree
.getContainerDataSource()).addChildItems(parent
);
306 private void showClassificationTaxa(UuidAndTitleCache
<TaxonNode
> rootNode
) {
307 final Collection
<UuidAndTitleCache
<TaxonNode
>> children
= CdmSpringContextHelper
.getTaxonNodeService().listChildNodesAsUuidAndTitleCache(rootNode
);
308 // Enable polling and set frequency to 0.5 seconds
309 UI
.getCurrent().setPollInterval(500);
310 taxonTree
.setEnabled(false);
311 taxonTree
.removeAllItems();
312 Notification
.show(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_LOADING_TAXA
));
314 new TreeUpdater(children
).start();
317 private UuidAndTitleCache
<TaxonNode
> getUuidAndTitleCacheFromRowId(Object classificationSelection
) {
318 String uuidString
= (String
) classificationBox
.getContainerProperty(classificationSelection
, "uuid").getValue(); //$NON-NLS-1$
319 Property
<Integer
> rootNodeContainerProperty
= null;
321 Collection
<?
> ids
= classificationBox
.getContainerPropertyIds();
322 //use for loop here because the case of the root node id columns differs between some DBs
323 for (Object id
: ids
) {
324 if(id
instanceof String
&& ((String
) id
).toLowerCase().equals("rootnode_id")){ //$NON-NLS-1$
325 rootNodeContainerProperty
= classificationBox
.getContainerProperty(classificationSelection
, id
);
329 int id
= rootNodeContainerProperty
.getValue();
330 String titleCache
= (String
) classificationBox
.getContainerProperty(classificationSelection
, "titleCache").getValue(); //$NON-NLS-1$
331 UUID uuid
= UUID
.fromString(uuidString
);
332 UuidAndTitleCache
<TaxonNode
> parent
= new UuidAndTitleCache
<>(uuid
, id
, titleCache
);
341 protected AreaAndTaxonSettingsPresenter
getPresenter() {
342 return new AreaAndTaxonSettingsPresenter();
345 private class TreeUpdater
extends Thread
{
347 private Collection
<UuidAndTitleCache
<TaxonNode
>> children
;
350 public TreeUpdater(Collection
<UuidAndTitleCache
<TaxonNode
>> children
) {
351 this.children
= children
;
356 UI
.getCurrent().access(new Runnable() {
359 taxonTree
.setContainerDataSource(new TaxonNodeContainer(children
));
361 Notification notification
= new Notification(Messages
.getLocalizedString(Messages
.AreaAndTaxonSettingsConfigWindow_LOADING_COMPLETE
));
362 notification
.setDelayMsec(500);
363 notification
.show(Page
.getCurrent());
364 taxonTree
.setEnabled(true);
365 taxonTree
.setSortContainerPropertyId("titleCache"); //$NON-NLS-1$
368 //disable polling when all taxa are loaded
369 UI
.getCurrent().setPollInterval(-1);