ref #7097 configure language based on vaadin session locale
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / distributionStatus / AreaAndTaxonSettingsConfigWindow.java
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.view.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.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;
41
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;
56
57 /**
58 *
59 * @author pplitzner
60 *
61 */
62 public class AreaAndTaxonSettingsConfigWindow
63 extends SettingsDialogWindowBase<AreaAndTaxonSettingsPresenter>
64 implements ValueChangeListener, ClickListener, ExpandListener{
65
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;
73
74 /**
75 * The constructor should first build the main layout, set the
76 * composition root and then do any custom initialization.
77 *
78 * The constructor will not be automatically regenerated by the
79 * visual editor.
80 * @param distributionTableView
81 */
82 public AreaAndTaxonSettingsConfigWindow(IDistributionTableView distributionTableView) {
83 super();
84 this.distributionTableView = distributionTableView;
85 }
86
87 @Override
88 protected void init() {
89 //init classification
90 Classification classification = presenter.getChosenClassification();
91 try {
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);
97 }
98 RowId classificationRow = null;
99 if(classification!=null){
100 classificationRow = new RowId(classification.getId());
101 }
102 else if(classificationBox.getItemIds().size()==1){
103 //only one classification exists
104 classificationRow = (RowId) classificationBox.getItemIds().iterator().next();
105 }
106 if(classificationRow!=null){
107 classificationBox.setValue(classificationRow);
108 showClassificationTaxa(getUuidAndTitleCacheFromRowId(classificationRow));
109 }
110
111 classificationBox.addValueChangeListener(this);
112 taxonFilter.addValueChangeListener(this);
113 taxonTree.addExpandListener(this);
114
115 //init areas
116 TermVocabulary<NamedArea> chosenAreaVoc = presenter.getChosenAreaVoc();
117 Container areaVocContainer = presenter.getAreaContainer();
118 if (areaVocContainer.size() == 1){
119 chosenAreaVoc = (TermVocabulary<NamedArea>)areaVocContainer.getItemIds().iterator().next();
120 }
121 distAreaBox.setContainerDataSource(areaVocContainer);
122 distAreaBox.setValue(chosenAreaVoc);
123 distAreaBox.addValueChangeListener(this);
124
125 if(chosenAreaVoc!=null){
126 NamedAreaContainer areaContainer = new NamedAreaContainer(chosenAreaVoc);
127 namedAreaList.setContainerDataSource(areaContainer);
128 }
129 Object selectedAreas = VaadinSession.getCurrent().getAttribute(DistributionEditorUtil.SATTR_SELECTED_AREAS);
130 namedAreaList.setValue(selectedAreas);
131
132 okButton.addClickListener(this);
133 cancelButton.addClickListener(this);
134 updateButtons();
135 }
136
137 @Override
138 protected AbstractLayout buildMainLayout() {
139
140 mainLayout = new VerticalLayout();
141 mainLayout.setSizeFull();
142
143 HorizontalLayout leftAndRightContainer = new HorizontalLayout();
144 leftAndRightContainer.setImmediate(false);
145 leftAndRightContainer.setSizeFull();
146 leftAndRightContainer.setMargin(true);
147 leftAndRightContainer.setSpacing(true);
148
149 VerticalLayout leftContainer = new VerticalLayout();
150 leftContainer.setImmediate(false);
151 leftContainer.setSpacing(true);
152 leftContainer.setSizeFull();
153
154 VerticalLayout rightContainer = new VerticalLayout();
155 rightContainer.setImmediate(false);
156 rightContainer.setSpacing(true);
157 rightContainer.setSizeFull();
158
159 //classification
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$
168
169 //taxonFilter
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);
174
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$
183
184 // named areas
185 namedAreaList = new ListSelect();
186 namedAreaList.setCaption(Messages.getLocalizedString(Messages.AreaAndTaxonSettingsConfigWindow_AREAS));
187 namedAreaList.setSizeFull();
188 namedAreaList.setMultiSelect(true);
189
190 //taxonomy
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);
198
199 leftContainer.addComponent(distAreaBox);
200 leftContainer.addComponent(namedAreaList);
201 leftContainer.setExpandRatio(distAreaBox, 0.1f);
202 leftContainer.setExpandRatio(namedAreaList, 0.9f);
203 leftContainer.setSizeFull();
204
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);
211
212 leftAndRightContainer.addComponent(leftContainer);
213 leftAndRightContainer.addComponent(rightContainer);
214
215 //button toolbar
216 HorizontalLayout buttonToolBar = createOkCancelButtons();
217
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);
223
224 return leftAndRightContainer;
225 }
226
227 @Override
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);
233 }
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));
239 }
240 else{
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);
249 }
250 taxonTree.setVisibleColumns("titleCache"); //$NON-NLS-1$
251 }
252 else{
253 UuidAndTitleCache<TaxonNode> parent = getUuidAndTitleCacheFromRowId(classificationBox.getValue());
254 showClassificationTaxa(parent);
255 }
256 }
257 }
258 else if(property==distAreaBox){
259 TermVocabulary<NamedArea> vocabulary = (TermVocabulary<NamedArea>) event.getProperty().getValue();
260 NamedAreaContainer container = new NamedAreaContainer(vocabulary);
261 namedAreaList.setContainerDataSource(container);
262 }
263 updateButtons();
264 }
265
266 @Override
267 protected boolean isValid() {
268 return classificationBox.getValue()!=null && distAreaBox.getValue()!=null;
269 }
270
271 @Override
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());
283 }
284 }
285 if(treeSelection.isEmpty() && CdmUtils.isNotBlank(taxonFilter.getValue())) {
286 for (UuidAndTitleCache<TaxonNode> uuidAndTitleCache : (Collection<UuidAndTitleCache<TaxonNode>>) taxonTree.getItemIds()) {
287 taxonNodes.add(uuidAndTitleCache.getUuid());
288 }
289 }
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);
293 window.close();
294 }
295 else if(source==cancelButton){
296 window.close();
297 }
298 }
299
300 @Override
301 public void nodeExpand(ExpandEvent event) {
302 UuidAndTitleCache<TaxonNode> parent = (UuidAndTitleCache<TaxonNode>) event.getItemId();
303 ((TaxonNodeContainer) taxonTree.getContainerDataSource()).addChildItems(parent);
304 }
305
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));
313
314 new TreeUpdater(children).start();
315 }
316
317 private UuidAndTitleCache<TaxonNode> getUuidAndTitleCacheFromRowId(Object classificationSelection) {
318 String uuidString = (String) classificationBox.getContainerProperty(classificationSelection, "uuid").getValue(); //$NON-NLS-1$
319 Property<Integer> rootNodeContainerProperty = null;
320
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);
326 break;
327 }
328 }
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);
333 return parent;
334 }
335
336
337 /**
338 * {@inheritDoc}
339 */
340 @Override
341 protected AreaAndTaxonSettingsPresenter getPresenter() {
342 return new AreaAndTaxonSettingsPresenter();
343 }
344
345 private class TreeUpdater extends Thread{
346
347 private Collection<UuidAndTitleCache<TaxonNode>> children;
348
349
350 public TreeUpdater(Collection<UuidAndTitleCache<TaxonNode>> children) {
351 this.children = children;
352 }
353
354 @Override
355 public void run() {
356 UI.getCurrent().access(new Runnable() {
357 @Override
358 public void run() {
359 taxonTree.setContainerDataSource(new TaxonNodeContainer(children));
360
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$
366 taxonTree.sort();
367
368 //disable polling when all taxa are loaded
369 UI.getCurrent().setPollInterval(-1);
370 }
371 });
372 }
373 }
374
375 }