TaxonNamePopupEditor layout and passing modes to basionym popup
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / name / TaxonNamePopupEditor.java
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.name;
10
11 import java.util.Collection;
12 import java.util.EnumSet;
13
14 import org.springframework.security.core.GrantedAuthority;
15
16 import com.vaadin.shared.ui.label.ContentMode;
17 import com.vaadin.ui.Alignment;
18 import com.vaadin.ui.CheckBox;
19 import com.vaadin.ui.GridLayout;
20 import com.vaadin.ui.Label;
21 import com.vaadin.ui.ListSelect;
22 import com.vaadin.ui.TextField;
23
24 import eu.etaxonomy.cdm.model.common.CdmBase;
25 import eu.etaxonomy.cdm.model.name.Rank;
26 import eu.etaxonomy.cdm.model.name.TaxonName;
27 import eu.etaxonomy.cdm.model.reference.Reference;
28 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
29 import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
30 import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
31 import eu.etaxonomy.cdm.vaadin.event.TaxonNameEditorAction;
32 import eu.etaxonomy.cdm.vaadin.security.AccessRestrictedView;
33 import eu.etaxonomy.cdm.vaadin.security.UserHelper;
34 import eu.etaxonomy.cdm.vaadin.util.converter.SetToListConverter;
35 import eu.etaxonomy.vaadin.component.SwitchableTextField;
36 import eu.etaxonomy.vaadin.component.ToManyRelatedEntitiesComboboxSelect;
37 import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
38 import eu.etaxonomy.vaadin.event.EditorActionType;
39 import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
40 import eu.etaxonomy.vaadin.permission.EditPermissionTester;
41
42 /**
43 * @author a.kohlbecker
44 * @since May 22, 2017
45 *
46 */
47 public class TaxonNamePopupEditor extends AbstractCdmPopupEditor<TaxonName, TaxonNameEditorPresenter> implements TaxonNamePopupEditorView, AccessRestrictedView {
48
49 private static final long serialVersionUID = -7037436241474466359L;
50
51 private final static int GRID_COLS = 4;
52
53 private final static int GRID_ROWS = 12;
54
55 private static final boolean HAS_BASIONYM_DEFAULT = false;
56
57 private TextField genusOrUninomialField;
58
59 private TextField infraGenericEpithetField;
60
61 private TextField specificEpithetField;
62
63 private TextField infraSpecificEpithetField;
64
65 private SwitchableTextField fullTitleCacheFiled;
66
67 private SwitchableTextField protectedNameCacheField;
68
69 private ToOneRelatedEntityCombobox<Reference> nomReferenceCombobox;
70
71 private TextField nomenclaturalReferenceDetail;
72
73 private TeamOrPersonField exBasionymAuthorshipField;
74
75 private TeamOrPersonField basionymAuthorshipField;
76
77 private ToManyRelatedEntitiesComboboxSelect<TaxonName> basionymsComboboxSelect;
78
79 private CheckBox basionymToggle;
80
81 private ListSelect rankSelect;
82
83 private TeamOrPersonField combinationAuthorshipField;
84
85 private TeamOrPersonField exCombinationAuthorshipField;
86
87 private EnumSet<TaxonNamePopupEditorMode> modesActive = EnumSet.noneOf(TaxonNamePopupEditorMode.class);
88
89 /**
90 * @param layout
91 * @param dtoType
92 */
93 public TaxonNamePopupEditor() {
94 super(new GridLayout(GRID_COLS, GRID_ROWS), TaxonName.class);
95 }
96
97 /**
98 * {@inheritDoc}
99 */
100 @Override
101 public String getWindowCaption() {
102 return "Name editor";
103 }
104
105
106
107 /**
108 * {@inheritDoc}
109 */
110 @Override
111 public int getWindowPixelWidth() {
112 return 700;
113 }
114
115 /**
116 * {@inheritDoc}
117 */
118 @Override
119 public void focusFirst() {
120 // titleField.focus();
121
122 }
123
124 /**
125 * {@inheritDoc}
126 */
127 @Override
128 protected String getDefaultComponentStyles() {
129 return "tiny";
130 }
131
132 /**
133 * {@inheritDoc}
134 */
135 @Override
136 protected void initContent() {
137
138 GridLayout grid = (GridLayout)getFieldLayout();
139 grid.setSizeFull();
140 grid.setSpacing(true);
141 grid.setColumnExpandRatio(0, 0.3f);
142 grid.setColumnExpandRatio(1, 0.3f);
143 grid.setColumnExpandRatio(2, 0.3f);
144 grid.setColumnExpandRatio(3, 0.0f);
145
146 /*
147 - nameType: preset, needs to be set in the presenter for new names
148 - appendedPhrase: -> TODO field
149 - nomenclaturalMicroReference: -> TODO field
150 - nomenclaturalReference -> field but disabled for REGISTRY
151 - rank -> SelectField which determines the visiblity of the other fields
152
153 - fullTitleCache + protectedFullTitleCache -> SwitchableTextField : ADVANCED_MODE
154 - nameCache + protectedNameCache -> SwitchableTextField : ADVANCED_MODE
155
156 - homotypicalGroup -> hidden
157 - typeDesignations -> hidden
158 - descriptions -> hidden
159 - taxonBases -> hidden
160 - registrations -> hidden
161
162 - relationsFromThisName-> TODO implement later
163 - relationsToThisName -> TODO implement later
164
165 - genusOrUninomial -> textField
166 - infraGenericEpithet -> textField
167 - specificEpithet -> textField
168 - infraSpecificEpithet -> textField
169
170 - authorshipCache + protectedAuthorshipCache -> SwitchableTextField : only ADVANCED_MODE and disabled for REGISTRY
171 - basionymAuthorship -> field but disabled for REGISTRY, basionym is set as nameRelationShip
172 - combinationAuthorship -> field but disabled for REGISTRY author team of the reference
173 - exCombinationAuthorship -> textField
174 - exBasionymAuthorship -> textField
175
176 - status -> TODO field
177 - monomHybrid -> TODO implement hybrids later
178 - binomHybrid -> TODO implement hybrids later
179 - trinomHybrid -> TODO implement hybrids later
180
181 - hybridParentRelations -> TODO implement hybrids later
182 - hybridChildRelations -> TODO implement hybrids later
183 - hybridFormula -> TODO implement hybrids later
184
185 ** ViralName attributes **
186 - acronym
187
188 ** BacterialName attributes **
189 - subGenusAuthorship
190 - nameApprobation
191 - breed
192 - publicationYear
193 - originalPublicationYear
194 - cultivarName
195 */
196
197 int row = 0;
198
199 rankSelect = new ListSelect("Rank");
200 rankSelect.setNullSelectionAllowed(false);
201 rankSelect.setRows(1);
202 rankSelect.setWidth(100, Unit.PERCENTAGE);
203 rankSelect.addValueChangeListener(e -> updateFieldVisibility((Rank)e.getProperty().getValue()));
204 addField(rankSelect, "rank", 0, row, 1, row);
205 grid.setComponentAlignment(rankSelect, Alignment.TOP_RIGHT);
206
207 basionymToggle = new CheckBox("With basionym");
208 basionymToggle.setValue(HAS_BASIONYM_DEFAULT);
209 basionymToggle.addValueChangeListener(e -> {
210 boolean enable = e.getProperty().getValue() != null && (Boolean)e.getProperty().getValue();
211 enableBasionymFields(enable);
212 });
213 basionymToggle.setStyleName(getDefaultComponentStyles());
214 grid.addComponent(basionymToggle, 2, row, 3, row);
215 grid.setComponentAlignment(basionymToggle, Alignment.BOTTOM_LEFT);
216 row++;
217 // fullTitleCache
218 fullTitleCacheFiled = addSwitchableTextField("Full title cache", "fullTitleCache", "protectedFullTitleCache", 0, row, GRID_COLS-1, row);
219 fullTitleCacheFiled.setWidth(100, Unit.PERCENTAGE);
220 row++;
221 protectedNameCacheField = addSwitchableTextField("Name cache", "nameCache", "protectedNameCache", 0, row, GRID_COLS-1, row);
222 protectedNameCacheField.setWidth(100, Unit.PERCENTAGE);
223 row++;
224 genusOrUninomialField = addTextField("Genus or uninomial", "genusOrUninomial", 0, row, 1, row);
225 genusOrUninomialField.setWidth(200, Unit.PIXELS);
226 infraGenericEpithetField = addTextField("Infrageneric epithet", "infraGenericEpithet", 2, row, 3, row);
227 infraGenericEpithetField.setWidth(200, Unit.PIXELS);
228 row++;
229 specificEpithetField = addTextField("Specific epithet", "specificEpithet", 0, row, 1, row);
230 specificEpithetField.setWidth(200, Unit.PIXELS);
231 infraSpecificEpithetField = addTextField("Infraspecific epithet", "infraSpecificEpithet", 2, row, 3, row);
232 infraSpecificEpithetField.setWidth(200, Unit.PIXELS);
233
234 row++;
235 grid.addComponent(new Label("Hint: <i>Edit nomenclatural authors in the nomenclatural reference.</i>", ContentMode.HTML), 0, row, 3, row);
236
237 row++;
238 combinationAuthorshipField = new TeamOrPersonField("combination author(s)");
239 combinationAuthorshipField.setWidth(100, Unit.PERCENTAGE);
240 addField(combinationAuthorshipField, "combinationAuthorship", 0, row, GRID_COLS-1, row);
241
242 row++;
243 nomReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("Nomenclatural reference", Reference.class);
244 nomReferenceCombobox.addClickListenerAddEntity(e -> getEventBus().publishEvent(
245 new ReferenceEditorAction(EditorActionType.ADD, null, nomReferenceCombobox, this)
246 ));
247 nomReferenceCombobox.addClickListenerEditEntity(e -> {
248 if(nomReferenceCombobox.getValue() != null){
249 getEventBus().publishEvent(
250 new ReferenceEditorAction(
251 EditorActionType.EDIT,
252 nomReferenceCombobox.getValue().getId(),
253 nomReferenceCombobox,
254 this)
255 );
256 }
257 });
258 // nomReferenceCombobox.setWidth(300, Unit.PIXELS);
259 nomReferenceCombobox.setWidth("100%");
260 addField(nomReferenceCombobox, "nomenclaturalReference", 0, row, 2, row);
261 nomenclaturalReferenceDetail = addTextField("Reference detail", "nomenclaturalMicroReference", 3, row, 3, row);
262 nomenclaturalReferenceDetail.setWidth(100, Unit.PIXELS);
263
264 row++;
265 exCombinationAuthorshipField = new TeamOrPersonField("Ex-combination author(s)");
266 exCombinationAuthorshipField.setWidth(100, Unit.PERCENTAGE);
267 addField(exCombinationAuthorshipField, "exCombinationAuthorship", 0, row, GRID_COLS-1, row);
268
269 // Basionym
270 row++;
271 basionymsComboboxSelect = new ToManyRelatedEntitiesComboboxSelect<TaxonName>(TaxonName.class, "Basionym");
272 basionymsComboboxSelect.setConverter(new SetToListConverter<TaxonName>());
273 addField(basionymsComboboxSelect, "basionyms", 0, row, 3, row);
274 basionymsComboboxSelect.setWidth(100, Unit.PERCENTAGE);
275 basionymsComboboxSelect.withEditButton(true);
276 basionymsComboboxSelect.setEditPermissionTester(new EditPermissionTester() {
277
278 @Override
279 public boolean userHasEditPermission(Object bean) {
280 return UserHelper.fromSession().userHasPermission((CdmBase)bean, CRUD.UPDATE, CRUD.DELETE);
281 }
282 });
283 basionymsComboboxSelect.setEditActionListener(e -> {
284
285 Object fieldValue = e.getSource().getValue();
286 Integer beanId = null;
287 if(fieldValue != null){
288 beanId = ((CdmBase)fieldValue).getId();
289
290 }
291 eventBus.publishEvent(new TaxonNameEditorAction(e.getAction(), beanId, e.getSource(), this));
292 });
293 grid.setComponentAlignment(basionymsComboboxSelect, Alignment.TOP_RIGHT);
294 row++;
295 basionymAuthorshipField = new TeamOrPersonField("Basionym author(s)");
296 basionymAuthorshipField.setWidth(100, Unit.PERCENTAGE);
297 addField(basionymAuthorshipField, "basionymAuthorship", 0, row, GRID_COLS-1, row);
298 row++;
299 exBasionymAuthorshipField = new TeamOrPersonField("Ex-basionym author(s)");
300 exBasionymAuthorshipField.setWidth(100, Unit.PERCENTAGE);
301 addField(exBasionymAuthorshipField, "exBasionymAuthorship", 0, row, GRID_COLS-1, row);
302
303
304
305 setAdvancedModeEnabled(true);
306 enableBasionymFields(HAS_BASIONYM_DEFAULT);
307 registerAdvancedModeComponents(fullTitleCacheFiled, protectedNameCacheField);
308 registerAdvancedModeComponents(basionymAuthorshipField.getCachFields());
309 registerAdvancedModeComponents(exBasionymAuthorshipField.getCachFields());
310 registerAdvancedModeComponents(combinationAuthorshipField.getCachFields());
311 registerAdvancedModeComponents(exCombinationAuthorshipField.getCachFields());
312 setAdvancedMode(false);
313
314 }
315
316 /**
317 * @param value
318 * @return
319 */
320 private void enableBasionymFields(boolean enable) {
321
322
323 basionymAuthorshipField.setVisible(enable);
324 exBasionymAuthorshipField.setVisible(enable);
325 basionymsComboboxSelect.setVisible(enable);
326 TaxonName taxonName = getBean();
327
328 if(taxonName != null){
329 if(modesActive.contains(TaxonNamePopupEditorMode.suppressReplacementAuthorshipData)){
330 basionymAuthorshipField.setVisible(taxonName.getBasionymAuthorship() != null);
331 }
332 updateFieldVisibility(taxonName.getRank());
333 }
334 }
335
336 /**
337 * @param rank
338 * @return
339 */
340 private void updateFieldVisibility(Rank rank) {
341 boolean isSpeciesOrBelow = !rank.isHigher(Rank.SPECIES());
342 // TODO use getField() instead and remove field references
343 infraSpecificEpithetField.setVisible(rank.isInfraSpecific());
344 specificEpithetField.setVisible(isSpeciesOrBelow);
345 infraGenericEpithetField.setVisible(rank.isInfraGenericButNotSpeciesGroup());
346 genusOrUninomialField.setCaption(isSpeciesOrBelow ? "Genus" : "Uninomial");
347 exCombinationAuthorshipField.setVisible(isSpeciesOrBelow);
348 }
349
350 @Override
351 protected void afterItemDataSourceSet() {
352 TaxonName taxonName = getBean();
353 boolean showBasionymSection = taxonName.getBasionyms().size() > 0
354 || taxonName.getBasionymAuthorship() != null
355 || taxonName.getExBasionymAuthorship() != null;
356 basionymToggle.setValue(showBasionymSection);
357
358 if(isModeEnabled(TaxonNamePopupEditorMode.suppressReplacementAuthorshipData)){
359 combinationAuthorshipField.setVisible(taxonName.getCombinationAuthorship() != null);
360 }
361 if(isModeEnabled(TaxonNamePopupEditorMode.nomenclaturalReferenceSectionEditingOnly) && getBean().getNomenclaturalReference() != null) {
362 nomReferenceCombobox.setCaption("Selection limited to nomenclatural reference and sections");
363 }
364
365 }
366
367 /**
368 * {@inheritDoc}
369 */
370 @Override
371 public boolean allowAnonymousAccess() {
372 return false;
373 }
374
375 /**
376 * {@inheritDoc}
377 */
378 @Override
379 public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
380 return null;
381 }
382
383 /**
384 * {@inheritDoc}
385 */
386 @Override
387 public ToOneRelatedEntityCombobox<Reference> getNomReferenceCombobox() {
388 return nomReferenceCombobox;
389 }
390
391 /**
392 * {@inheritDoc}
393 */
394 @Override
395 public ToManyRelatedEntitiesComboboxSelect<TaxonName> getBasionymComboboxSelect() {
396 return basionymsComboboxSelect;
397 }
398
399 /**
400 * {@inheritDoc}
401 */
402 @Override
403 public ListSelect getRankSelect() {
404 return rankSelect;
405 }
406
407 /**
408 * @return the exBasionymAuthorshipField
409 */
410 @Override
411 public TeamOrPersonField getExBasionymAuthorshipField() {
412 return exBasionymAuthorshipField;
413 }
414
415 /**
416 * @return the basionymAuthorshipField
417 */
418 @Override
419 public TeamOrPersonField getBasionymAuthorshipField() {
420 return basionymAuthorshipField;
421 }
422
423 /**
424 * @return the combinationAuthorshipField
425 */
426 @Override
427 public TeamOrPersonField getCombinationAuthorshipField() {
428 return combinationAuthorshipField;
429 }
430
431 /**
432 * @return the exCombinationAuthorshipField
433 */
434 @Override
435 public TeamOrPersonField getExCombinationAuthorshipField() {
436 return exCombinationAuthorshipField;
437 }
438
439 @Override
440 public void enableMode(TaxonNamePopupEditorMode mode){
441 modesActive.add(mode);
442 }
443
444 @Override
445 public boolean isModeEnabled(TaxonNamePopupEditorMode mode){
446 return modesActive.contains(mode);
447 }
448
449 @Override
450 public void disableMode(TaxonNamePopupEditorMode mode){
451 modesActive.remove(mode);
452 }
453
454 @Override
455 public EnumSet<TaxonNamePopupEditorMode> getModesActive(){
456 return modesActive;
457 }
458
459 @Override
460 public CheckBox getBasionymToggle() {
461 return basionymToggle;
462 }
463
464
465 }