Project

General

Profile

Download (4.57 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2018 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.vaadin.component;
10

    
11
import java.lang.reflect.Field;
12

    
13
import org.vaadin.viritin.fields.LazyComboBox;
14
import org.vaadin.viritin.fields.TypedSelect;
15

    
16
import com.vaadin.ui.AbstractField;
17
import com.vaadin.ui.AbstractSelect;
18
import com.vaadin.ui.ComboBox;
19

    
20
public class ReloadableLazyComboBox<T> extends LazyComboBox<T> implements ReloadableSelect, EntitySupport<T> {
21

    
22

    
23
    private static final long serialVersionUID = -4833661351090992884L;
24

    
25
    static Field lazySelectInternalValueField;
26
    static Field internalSelectField;
27
    static {
28
        try {
29
            lazySelectInternalValueField = AbstractField.class.getDeclaredField("value");
30
            lazySelectInternalValueField.setAccessible(true);
31
            lazySelectInternalValueField.setAccessible(true);
32

    
33
            internalSelectField = TypedSelect.class.getDeclaredField("select");
34
            internalSelectField.setAccessible(true);
35

    
36
        } catch (NoSuchFieldException | SecurityException e) {
37
            // NONE of these should ever happen, maybe only after dependency upgrades
38
            throw new RuntimeException(e);
39
        }
40
    }
41

    
42
    /**
43
     * @param itemType
44
     */
45
    public ReloadableLazyComboBox(Class<T> itemType) {
46
        super(itemType);
47
    }
48

    
49
    /**
50
     * {@inheritDoc}
51
     */
52
    @Override
53
    public void reload() {
54
        // in the LazyComboBox.initList() scrollToSelectedItem is set to false for better performance
55
        // but this breaks the refresh, so we need to set it now so that it can
56
        // affect the next component repaint which is triggered in refresh()
57
        ComboBox comboBox = (ComboBox)getSelect();
58
        comboBox.setScrollToSelectedItem(true);
59
        refresh(); // reload from persistence
60
        discard(); // reload from property data source
61
    }
62

    
63

    
64
    /**
65
     * This method allows updating the value even if the equals check done
66
     * in {@link com.vaadin.ui.AbstractField#setValue(Object)} would return true.
67
     * This is important when working with entity beans which have been modified.
68
     * For entity beans equality given when the type and id are equal, so data
69
     * modification is not respected by this concept of equality. Such entities
70
     * would be skipped in the {@link com.vaadin.ui.AbstractField#setValue(Object) setValue()}
71
     * method and {@link ValueChangeListener ValueChangeListeners} like the
72
     * {@link eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader ToOneRelatedEntityReloader}
73
     *  would not be triggered.
74
     *  <p>
75
     *  To circumvent this problem this method checks for object identity with the internal value of
76
     *  the select field and resets the internal select fields to cause the equality check to fail during
77
     *  the subsequent execution of the setValue() method. By this it is guaranteed the the value will be
78
     *  updated and that
79
     *  the {@link eu.etaxonomy.cdm.vaadin.event.ToOneRelatedEntityReloader ToOneRelatedEntityReloaders}
80
     *  will be triggered.
81
     *
82
     * @param bean
83
     */
84
    @Override
85
    public void replaceEntityValue(T bean){
86

    
87
        if(bean != internalValueByFieldAccess()){
88
            resetInternalValue();
89
        }
90
        setValue(bean);
91
    }
92

    
93
    /**
94
     *
95
     */
96
    private T internalValueByFieldAccess(){
97
        try {
98
            return (T) lazySelectInternalValueField.get(this);
99
        } catch (IllegalArgumentException | IllegalAccessException e) {
100
            // NONE of these should ever happen, maybe only after dependency upgrades
101
            throw new RuntimeException(e);
102
        }
103
    }
104

    
105
    /**
106
     * Directly sets the <b>internal value fields</b> of the nested <code>LazyComboBox</code> to <code>null</code>.
107
     *  <b>This method short circuits the setValue() method execution cascade completely</b>
108
     *  <p>
109
     *  See {@link #refreshSelectedValue(Object)} more more background information.
110
     */
111
    public void resetInternalValue() {
112

    
113
        try {
114
            AbstractSelect internalSelect = (AbstractSelect) internalSelectField.get(this);
115
            lazySelectInternalValueField.set(this, (Object)null);
116
            lazySelectInternalValueField.set(internalSelect, (Object)null);
117
        } catch (SecurityException | IllegalAccessException | IllegalArgumentException  e) {
118
            // NONE of these should ever happen, maybe only after dependency upgrades
119
            throw new RuntimeException(e);
120
        }
121
    }
122

    
123

    
124
}
(6-6/14)