4885020ffb90cc097e34fe20f5cc32d45abadeeb
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / reference / ReferencePopupEditor.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.reference;
10
11 import java.util.Collection;
12 import java.util.EnumSet;
13 import java.util.HashMap;
14 import java.util.LinkedHashMap;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.apache.log4j.Logger;
19 import org.springframework.context.annotation.Scope;
20 import org.springframework.security.core.GrantedAuthority;
21
22 import com.vaadin.spring.annotation.SpringComponent;
23 import com.vaadin.ui.AbstractField;
24 import com.vaadin.ui.Alignment;
25 import com.vaadin.ui.Component;
26 import com.vaadin.ui.Field;
27 import com.vaadin.ui.GridLayout;
28 import com.vaadin.ui.ListSelect;
29 import com.vaadin.ui.TextField;
30
31 import eu.etaxonomy.cdm.model.reference.Reference;
32 import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions;
33 import eu.etaxonomy.cdm.model.reference.ReferencePropertyDefinitions.UnimplemetedCaseException;
34 import eu.etaxonomy.cdm.model.reference.ReferenceType;
35 import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
36 import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
37 import eu.etaxonomy.cdm.vaadin.component.common.VerbatimTimePeriodField;
38 import eu.etaxonomy.cdm.vaadin.event.ReferenceEditorAction;
39 import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
40 import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
41 import eu.etaxonomy.cdm.vaadin.util.converter.DoiConverter;
42 import eu.etaxonomy.cdm.vaadin.util.converter.UriConverter;
43 import eu.etaxonomy.vaadin.component.SwitchableTextField;
44 import eu.etaxonomy.vaadin.component.ToOneRelatedEntityCombobox;
45 import eu.etaxonomy.vaadin.event.EditorActionType;
46 import eu.etaxonomy.vaadin.mvp.AbstractCdmPopupEditor;
47 import eu.etaxonomy.vaadin.util.PropertyIdPath;
48
49 /**
50 * @author a.kohlbecker
51 * @since Apr 4, 2017
52 *
53 */
54 @SpringComponent
55 @Scope("prototype")
56 public class ReferencePopupEditor extends AbstractCdmPopupEditor<Reference, ReferenceEditorPresenter> implements ReferencePopupEditorView, AccessRestrictedView {
57
58 private static final long serialVersionUID = -4347633563800758815L;
59
60 private static final Logger logger = Logger.getLogger(ReferencePopupEditor.class);
61
62 private TextField titleField;
63
64 private final static int GRID_COLS = 4; // 12 would fits for 2,3, and 4 Components per row
65
66 private final static int GRID_ROWS = 10;
67
68 private ListSelect typeSelect;
69
70 private ToOneRelatedEntityCombobox<Reference> inReferenceCombobox;
71
72 private TeamOrPersonField authorshipField;
73
74 private EnumSet<ReferenceType> referenceTypes = EnumSet.allOf(ReferenceType.class);
75
76 private static Map<String,String> propertyNameLabelMap = new HashMap<>();
77
78 private int variableGridStartRow;
79
80 private int variableGridLastRow;
81
82 /**
83 * Used to record the fields from the variable grid part in their original order.
84 */
85 private LinkedHashMap<String, Field<?>> adaptiveFields = new LinkedHashMap<>();
86
87 static {
88 propertyNameLabelMap.put("inReference", "In reference");
89 propertyNameLabelMap.put("inJournal", "In journal");
90 propertyNameLabelMap.put("inSeries", "In series");
91 propertyNameLabelMap.put("inBook", "In book");
92 }
93
94 /**
95 * @param layout
96 * @param dtoType
97 */
98 public ReferencePopupEditor() {
99 super(new GridLayout(GRID_COLS, GRID_ROWS), Reference.class);
100 }
101
102 @Override
103 protected void initContent() {
104 GridLayout grid = (GridLayout)getFieldLayout();
105 grid.setSpacing(true);
106 grid.setMargin(true);
107
108 /*
109 "type",
110 "uri",
111 "abbrevTitleCache",
112 "protectedAbbrevTitleCache",
113 "nomenclaturallyRelevant",
114 "authorship",
115 "referenceAbstract",
116 "title",
117 "abbrevTitle",
118 "editor",
119 "volume",
120 "pages",
121 "edition",
122 "isbn",
123 "issn",
124 "doi",
125 "seriesPart",
126 "datePublished",
127 "publisher",
128 "placePublished",
129 "institution",
130 "school",
131 "organization",
132 "inReference"
133 */
134 int row = 0;
135 VerbatimTimePeriodField timePeriodField = new VerbatimTimePeriodField("Date published");
136 addField(timePeriodField, "datePublished", 0, row, 1, row);
137 typeSelect = new ListSelect("Reference type");
138 typeSelect.addItems(referenceTypes);
139 typeSelect.setNullSelectionAllowed(false);
140 typeSelect.setRows(1);
141 typeSelect.addValueChangeListener(e -> updateFieldVisibility((ReferenceType)e.getProperty().getValue()));
142 addField(typeSelect, "type", GRID_COLS - 1, row);
143 grid.setComponentAlignment(typeSelect, Alignment.TOP_RIGHT);
144 row++;
145
146 SwitchableTextField titleCacheField = addSwitchableTextField("Reference cache", "titleCache", "protectedTitleCache", 0, row, GRID_COLS-1, row);
147 titleCacheField.setWidth(100, Unit.PERCENTAGE);
148 row++;
149
150 SwitchableTextField abbrevTitleCacheField = addSwitchableTextField("Abbrev. cache", "abbrevTitleCache", "protectedAbbrevTitleCache", 0, row, GRID_COLS-1, row);
151 abbrevTitleCacheField.setWidth(100, Unit.PERCENTAGE);
152 row++;
153
154 titleField = addTextField("Title", "title", 0, row, GRID_COLS-1, row);
155 titleField.setWidth(100, Unit.PERCENTAGE);
156 row++;
157 addTextField("Nomenclatural title", "abbrevTitle", 0, row, GRID_COLS-1, row).setWidth(100, Unit.PERCENTAGE);
158 row++;
159
160 authorshipField = new TeamOrPersonField("Author(s)", TeamOrPersonBaseCaptionGenerator.CacheType.BIBLIOGRAPHIC_TITLE);
161 authorshipField.setWidth(100, Unit.PERCENTAGE);
162 addField(authorshipField, "authorship", 0, row, GRID_COLS -1, row);
163 row++;
164
165 inReferenceCombobox = new ToOneRelatedEntityCombobox<Reference>("In-reference", Reference.class);
166 inReferenceCombobox.setWidth(100, Unit.PERCENTAGE);
167 inReferenceCombobox.addClickListenerAddEntity(e -> getViewEventBus().publish(this,
168 new ReferenceEditorAction(EditorActionType.ADD, e.getButton(), inReferenceCombobox, this)
169 ));
170 inReferenceCombobox.addClickListenerEditEntity(e -> {
171 if(inReferenceCombobox.getValue() != null){
172 getViewEventBus().publish(this,
173 new ReferenceEditorAction(
174 EditorActionType.EDIT,
175 inReferenceCombobox.getValue().getUuid(),
176 e.getButton(),
177 inReferenceCombobox,
178 this)
179 );
180 }
181 });
182 addField(inReferenceCombobox, "inReference", 0, row, GRID_COLS -1, row);
183 row++;
184
185 variableGridStartRow = row;
186 addTextField("Series", "seriesPart", 0, row).setWidth(100, Unit.PERCENTAGE);
187 addTextField("Volume", "volume", 1, row).setWidth(100, Unit.PERCENTAGE);
188 addTextField("Pages", "pages", 2, row).setWidth(100, Unit.PERCENTAGE);
189 addTextField("Edition", "edition", 3, row).setWidth(100, Unit.PERCENTAGE);
190 row++;
191
192 addTextField("Place published", "placePublished", 0, row, 0, row).setWidth(100, Unit.PERCENTAGE);
193 TextField publisherField = addTextField("Publisher", "publisher", 1, row, 1, row);
194 publisherField.setWidth(100, Unit.PERCENTAGE);
195 addTextField("Editor", "editor", 2, row).setWidth(100, Unit.PERCENTAGE);
196 row++;
197
198 addTextField("ISSN", "issn", 0, row).setWidth(100, Unit.PERCENTAGE);
199 addTextField("ISBN", "isbn", 1, row).setWidth(100, Unit.PERCENTAGE);
200 TextFieldNFix doiField = new TextFieldNFix("DOI");
201 doiField.setConverter(new DoiConverter());
202 doiField.setWidth(100, Unit.PERCENTAGE);
203 addField(doiField, "doi", 2, row);
204 TextFieldNFix uriField = new TextFieldNFix("Uri");
205 uriField.setConverter(new UriConverter());
206 uriField.setWidth(100, Unit.PERCENTAGE);
207 addField(uriField, "uri", 3, row);
208
209
210 variableGridLastRow = row;
211
212 // titleField.setRequired(true);
213 // publisherField.setRequired(true);
214
215 setAdvancedModeEnabled(true);
216 registerAdvancedModeComponents(titleCacheField, abbrevTitleCacheField);
217 registerAdvancedModeComponents(authorshipField.getCachFields());
218 setAdvancedMode(false);
219
220 }
221
222 /**
223 * @param value
224 * @return
225 */
226 private Object updateFieldVisibility(ReferenceType referenceType) {
227
228 GridLayout grid = (GridLayout)getFieldLayout();
229
230 initAdaptiveFields();
231
232 // clear the variable grid part
233 for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
234 for(int x=0; x < grid.getColumns(); x++){
235 grid.removeComponent(x, row);
236 }
237 }
238
239 // set cursor at the beginning of the variable grid part
240 grid.setCursorY(variableGridStartRow);
241 grid.setCursorX(0);
242
243 // place the fields which are required for the given referenceType in the variable grid part while
244 // and retain the original order which is recorded in the adaptiveFields
245 try {
246 Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(referenceType);
247
248 for(String fieldName : adaptiveFields.keySet()){ // iterate over the LinkedHashMap to retain the original order of the fields
249 if(fieldPropertyDefinition.containsKey(fieldName)){
250 Field<?> field = adaptiveFields.get(fieldName);
251 grid.addComponent(field);
252 String propertyName = fieldPropertyDefinition.get(fieldName);
253 if(propertyName != fieldName){
254 field.setCaption(propertyNameLabelMap.get(propertyName));
255 }
256 }
257 }
258 } catch (UnimplemetedCaseException e) {
259 logger.error(e);
260 // enable all fields
261 setAllFieldsVisible(true);
262 // fix inReference label
263 getField("inReference").setCaption(propertyNameLabelMap.get("inReference"));
264 }
265
266 EnumSet<ReferenceType> hideNomTitle = EnumSet.of(ReferenceType.Article, ReferenceType.Section, ReferenceType.BookSection, ReferenceType.InProceedings, ReferenceType.PrintSeries);
267 EnumSet<ReferenceType> hideTitle = EnumSet.of(ReferenceType.Section, ReferenceType.BookSection);
268 getField("abbrevTitle").setVisible(!hideNomTitle.contains(referenceType));
269 getField("title").setVisible(!hideTitle.contains(referenceType));
270
271 return null;
272 }
273
274 /**
275 * @param grid
276 */
277 protected void initAdaptiveFields() {
278 GridLayout grid = (GridLayout)getFieldLayout();
279 // initialize the map of adaptive fields
280 if(adaptiveFields.isEmpty()){
281 try{
282 Map<String, String> fieldPropertyDefinition = ReferencePropertyDefinitions.fieldPropertyDefinition(null);
283 Set<String> fieldNames = fieldPropertyDefinition.keySet();
284 for(int row = variableGridStartRow; row <= variableGridLastRow; row++){
285 for(int x=0; x < grid.getColumns(); x++){
286 Component c = grid.getComponent(x, row);
287 logger.debug("initAdaptiveFields() - y: " + row + " x: " + x + " component:" + (c != null ? c.getClass().getSimpleName(): "NULL"));
288 if(c != null && c instanceof Field){
289 Field<?> field = (Field<?>)c;
290 PropertyIdPath propertyIdPath = boundPropertyIdPath(field);
291 logger.debug("initAdaptiveFields() - " + field.getCaption() + " -> " + propertyIdPath);
292 if(propertyIdPath != null && fieldNames.contains(propertyIdPath.toString())){
293 adaptiveFields.put(propertyIdPath.toString(), field);
294 }
295 }
296 }
297 }
298 } catch (UnimplemetedCaseException e) {
299 throw new RuntimeException(e);
300 }
301 }
302 }
303
304 protected void setAllFieldsVisible(boolean visible){
305 GridLayout grid = (GridLayout)getFieldLayout();
306 for(Component c : grid){
307 if(AbstractField.class.isAssignableFrom(c.getClass())){
308 c.setVisible(visible);
309 }
310 }
311 }
312
313 /**
314 * {@inheritDoc}
315 */
316 @Override
317 public String getWindowCaption() {
318 return "Reference editor";
319 }
320
321 /**
322 * {@inheritDoc}
323 */
324 @Override
325 protected String getDefaultComponentStyles() {
326 return "tiny";
327 }
328
329 /**
330 * {@inheritDoc}
331 */
332 @Override
333 public void focusFirst() {
334 titleField.focus();
335 }
336
337 /**
338 * {@inheritDoc}
339 */
340 @Override
341 public boolean isResizable() {
342 return false;
343 }
344
345 /**
346 * {@inheritDoc}
347 */
348 @Override
349 public boolean allowAnonymousAccess() {
350 return false;
351 }
352
353 /**
354 * {@inheritDoc}
355 */
356 @Override
357 public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
358 return null;
359 }
360
361 @Override
362 public ListSelect getTypeSelect() {
363 return typeSelect;
364 }
365
366 /**
367 * {@inheritDoc}
368 */
369 @Override
370 public ToOneRelatedEntityCombobox<Reference> getInReferenceCombobox() {
371 return inReferenceCombobox;
372 }
373
374 /**
375 * {@inheritDoc}
376 */
377 @Override
378 public TeamOrPersonField getAuthorshipField() {
379 return authorshipField;
380 }
381
382 public void withReferenceTypes(EnumSet<ReferenceType> types){
383 this.referenceTypes = types;
384 if(typeSelect != null){
385 typeSelect.removeAllItems();
386 typeSelect.addItems(referenceTypes);
387 }
388 }
389
390
391 }