Project

General

Profile

Download (4.61 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
//    boolean originalScrollToSelect;
26

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

    
35
            internalSelectField = TypedSelect.class.getDeclaredField("select");
36
            internalSelectField.setAccessible(true);
37

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

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

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

    
65

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

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

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

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

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

    
125

    
126
}
(6-6/14)