Project

General

Profile

Revision 837c73ee

ID837c73eed01c6f26516c646a4c36f7294ab8db65
Parent c46954e3
Child 92d4dbe0

Added by Andreas Kohlbecker about 2 years ago

ref #6673 PojoEventListenerManager to manage pojos annotated with @EventLister

View differences:

src/main/java/eu/etaxonomy/cdm/addon/config/CdmVaadinConfiguration.java
52 52
        "eu.etaxonomy.cdm.dataInserter",
53 53
        "eu.etaxonomy.cdm.service",
54 54
        "eu.etaxonomy.cdm.vaadin.component", // for the FieldFactories
55
        "eu.etaxonomy.cdm.mock" // FIXME remove once mocks are no longer needed
55
        "org.springframework.context.event"
56 56
        },
57 57
        // exclude UI classes, these are provided via the @Bean annotated methods below
58 58
        excludeFilters={@Filter(
src/main/java/eu/etaxonomy/cdm/vaadin/view/reference/ReferenceEditorPresenter.java
11 11
import java.util.Arrays;
12 12
import java.util.List;
13 13

  
14
import org.apache.log4j.Logger;
15
import org.springframework.context.annotation.Scope;
14 16
import org.springframework.context.event.EventListener;
15 17
import org.springframework.transaction.TransactionStatus;
16 18

  
17 19
import com.vaadin.data.Item;
18 20
import com.vaadin.data.util.BeanItemContainer;
19 21
import com.vaadin.spring.annotation.SpringComponent;
20
import com.vaadin.spring.annotation.ViewScope;
21 22
import com.vaadin.ui.ListSelect;
22 23

  
23 24
import eu.etaxonomy.cdm.model.reference.Reference;
......
35 36
 *
36 37
 */
37 38
@SpringComponent
38
@ViewScope
39
@Scope("prototype")
39 40
public class ReferenceEditorPresenter extends AbstractCdmEditorPresenter<Reference, ReferencePopupEditorView> {
40 41

  
41 42
    private static final long serialVersionUID = -7926116447719010837L;
42 43

  
44
    private static final Logger logger = Logger.getLogger(ReferenceEditorPresenter.class);
45

  
43 46
    ReferencePopupEditor inReferencePopup = null;
44 47

  
48
    public ReferenceEditorPresenter() {
49
        logger.trace("CONTRUCTOR");
50
    }
51

  
45 52
    /**
46 53
     * {@inheritDoc}
47 54
     */
......
64 71
    */
65 72
   @EventListener(condition = "#editorAction.source != null")
66 73
   public void onReferenceEditorAction(ReferenceEditorAction editorAction){
74
       if(isViewLess()){
75
           return;
76
       }
67 77
       if(ToOneRelatedEntityField.class.isAssignableFrom(editorAction.getSource().getClass())){
68 78
           if(editorAction.isAddAction()){
69 79
               Reference reference = ReferenceFactory.newGeneric();
......
83 93

  
84 94
   @EventListener
85 95
   public void doDoneWithPopupEvent(DoneWithPopupEvent event){
96
       if(isViewLess()){
97
           return;
98
       }
86 99
       if(event.getPopup().equals(inReferencePopup)){
87 100
           if(event.getReason().equals(Reason.SAVE)){
88 101
               Reference bean = inReferencePopup.getBean();
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractCdmEditorPresenter.java
147 147
     * @return
148 148
     */
149 149
    private boolean isResponsible(EditorViewEvent event){
150
        return event.getView().getClass().equals(getViewType());
150

  
151
        return !isViewLess() && event.getView().getClass().equals(getViewType());
151 152
    }
152 153

  
153 154
    @Override
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractEditorPresenter.java
56 56

  
57 57
    protected abstract void saveBean(DTO bean);
58 58

  
59
    /**
60
     *
61
     * @return
62
     * @deprecated see #6673
63
     */
64
    @Deprecated
65
    protected boolean isViewLess() {
66
        return getView() == null;
67
    }
59 68

  
60 69

  
61 70
}
src/main/java/eu/etaxonomy/vaadin/mvp/AbstractPopupEditor.java
109 109

  
110 110
        save = new Button("Save", FontAwesome.SAVE);
111 111
        save.setStyleName(ValoTheme.BUTTON_PRIMARY);
112
        save.addClickListener(e -> onSaveClicked());
112
        save.addClickListener(e -> save());
113 113

  
114 114
        cancel = new Button("Cancel", FontAwesome.TRASH);
115
        cancel.addClickListener(e -> onCancelClicked());
115
        cancel.addClickListener(e -> cancel());
116 116

  
117 117
        buttonLayout.addComponents(save, cancel);
118 118
        buttonLayout.setExpandRatio(save, 1);
......
238 238
    }
239 239

  
240 240

  
241
    private void onCancelClicked() {
241
    /**
242
     * Cancel editing and discard all modifications.
243
     */
244
    @Override
245
    public void cancel() {
242 246
        fieldGroup.discard();
243 247
        eventBus.publishEvent(new DoneWithPopupEvent(this, Reason.CANCEL));
244 248
    }
245 249

  
246
    private void onSaveClicked() {
250
    /**
251
     * Save the changes made in the editor.
252
     */
253
    private void save() {
247 254
        try {
248 255
            fieldGroup.commit();
249 256
        } catch (CommitException e) {
......
502 509
    protected void afterItemDataSourceSet() {
503 510

  
504 511
    }
512

  
513
    // ------------------------ issue related temporary solutions --------------------- //
514
    /**
515
     *
516
     * @return
517
     * @deprecated see #6673
518
     */
519
    @Deprecated
520
    public P presenter() {
521
        return getPresenter();
522
    }
505 523
}
src/main/java/eu/etaxonomy/vaadin/ui/navigation/NavigationManager.java
4 4

  
5 5
import com.vaadin.navigator.View;
6 6

  
7
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
7 8
import eu.etaxonomy.vaadin.ui.view.PopupView;
8 9

  
9 10
public interface NavigationManager {
......
12 13

  
13 14
	<T extends PopupView> T showInPopup(Class<T> popupType);
14 15

  
16
	public List<AbstractEditorPresenter<?,?>> getPopupEditorPresenters();
17

  
15 18
	void reloadCurrentView();
16 19

  
17 20
	/**
src/main/java/eu/etaxonomy/vaadin/ui/navigation/NavigationManagerBean.java
13 13
import org.springframework.context.ApplicationEventPublisher;
14 14
import org.springframework.context.annotation.Lazy;
15 15
import org.springframework.context.event.EventListener;
16
import org.springframework.context.event.PojoEventListenerManager;
16 17

  
17 18
import com.vaadin.navigator.ViewChangeListener;
18 19
import com.vaadin.navigator.ViewDisplay;
......
25 26
import com.vaadin.ui.Window;
26 27

  
27 28
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
29
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
30
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
28 31
import eu.etaxonomy.vaadin.ui.UIInitializedEvent;
29 32
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
30 33
import eu.etaxonomy.vaadin.ui.view.PopupView;
......
46 49
	private ViewChangeListener viewChangeListener;
47 50

  
48 51
	@Autowired
52
	private PojoEventListenerManager eventListenerManager;
53

  
54
	@Autowired
49 55
    private UserHelper userHelper;
50 56

  
51 57
	private Map<PopupView, Window> popupMap;
......
118 124

  
119 125
	    PopupView popupView =  findPopupView(popupType).get(); // TODO make better use of Optional
120 126

  
127
	    if(AbstractPopupEditor.class.isAssignableFrom(popupView.getClass())){
128
	        AbstractEditorPresenter presenter = ((AbstractPopupEditor)popupView).presenter();
129
	        eventListenerManager.addEventListeners(presenter);
130
	    }
131

  
121 132
		Window window = new Window();
122 133
		window.setCaption(popupView.getWindowCaption());
123 134
		window.center();
......
128 139
		window.setCaptionAsHtml(popupView.isWindowCaptionAsHtml());
129 140
		window.setWidth(popupView.getWindowPixelWidth(), Unit.PIXELS);
130 141
		window.setContent(popupView.asComponent());
142
		window.addCloseListener(e -> popupView.cancel());
131 143
		UI.getCurrent().addWindow(window);
132 144
		popupView.viewEntered();
133 145
		popupView.focusFirst();
......
139 151

  
140 152
    @EventListener
141 153
	protected void onDoneWithTheEditor(DoneWithPopupEvent e) {
142
		Window window = popupMap.get(e.getPopup());
154

  
155
		PopupView popup = e.getPopup();
156
        Window window = popupMap.get(popup);
143 157
		if (window != null) {
144 158
			window.close();
145
			popupMap.remove(e.getPopup());
159
			popupMap.remove(popup);
160
		}
161
		if(AbstractPopupEditor.class.isAssignableFrom(popup.getClass())){
162
		    AbstractEditorPresenter presenter = ((AbstractPopupEditor)popup).presenter();
163
		    eventListenerManager.removeEventListeners(presenter);
146 164
		}
147 165
	}
148 166

  
......
180 198
        }
181 199
        return Arrays.asList(substate.split("/"));
182 200
    }
201

  
202
    /**
203
     * {@inheritDoc}
204
     */
205
    @Override
206
    public List<AbstractEditorPresenter<?, ?>> getPopupEditorPresenters() {
207
        // TODO Auto-generated method stub
208
        return null;
209
    }
183 210
}
src/main/java/eu/etaxonomy/vaadin/ui/view/PopupView.java
42 42
     */
43 43
    void focusFirst();
44 44

  
45
    /**
46
     * Cancel any operation in progress and close the view.
47
     */
48
    public void cancel();
49

  
45 50

  
46 51
}
src/main/java/org/springframework/context/event/ApplicationListenerPojoMethodAdapter.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 org.springframework.context.event;
10

  
11
import java.lang.reflect.Method;
12

  
13
/**
14
 * A special ApplicationListenerMethodAdapter for prototype spring beans.
15
 *
16
 * @author a.kohlbecker
17
 * @since May 30, 2017
18
 *
19
 */
20
public class ApplicationListenerPojoMethodAdapter extends ApplicationListenerMethodAdapter {
21

  
22
    PojoEventListenerManager eventListenerManager = null;
23

  
24
    private Object o;
25

  
26
    /**
27
     * @param beanName
28
     * @param targetClass
29
     * @param method
30
     */
31
    public ApplicationListenerPojoMethodAdapter(String beanName, Class<?> targetClass, Method method, Object o) {
32
        super(beanName, targetClass, method);
33
        this.o = o;
34
    }
35

  
36
    /**
37
     * {@inheritDoc}
38
     */
39
    @Override
40
    protected Object getTargetBean() {
41
        return o;
42
    }
43

  
44

  
45

  
46
}
src/main/java/org/springframework/context/event/DefaultPojoEventListenerManager.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 org.springframework.context.event;
10

  
11
import java.lang.reflect.Method;
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.HashMap;
15
import java.util.Map;
16

  
17
import org.springframework.beans.BeansException;
18
import org.springframework.beans.factory.annotation.Autowired;
19
import org.springframework.context.ApplicationContext;
20
import org.springframework.context.ApplicationContextAware;
21
import org.springframework.context.ApplicationListener;
22
import org.springframework.core.annotation.AnnotationUtils;
23
import org.springframework.util.ReflectionUtils;
24

  
25
import com.vaadin.spring.annotation.SpringComponent;
26
import com.vaadin.spring.annotation.UIScope;
27

  
28
/**
29
 * @author a.kohlbecker
30
 * @since May 29, 2017
31
 *
32
 */
33
@SpringComponent
34
@UIScope
35
public class DefaultPojoEventListenerManager implements PojoEventListenerManager, ApplicationContextAware {
36

  
37
    @Autowired
38
    private ApplicationEventMulticaster applicationEventMulticaster;
39

  
40
    private final EventExpressionEvaluator evaluator = new EventExpressionEvaluator();
41

  
42
    private Map<Object, Collection<ApplicationListener<?>>> listenerMap = new HashMap<>();
43

  
44
    private ApplicationContext applicationContext;
45

  
46
    @Override
47
    public void addEventListeners(Object o){
48

  
49
        Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(o.getClass());
50
        for (Method method : methods) {
51
            EventListener eventListener = AnnotationUtils.findAnnotation(method, EventListener.class);
52
            if (eventListener == null) {
53
                continue;
54
            }
55
            ApplicationListenerPojoMethodAdapter applicationListener = new ApplicationListenerPojoMethodAdapter(o.toString(), o.getClass(), method, o);
56
            applicationListener.init(this.applicationContext, this.evaluator);
57

  
58
            applicationEventMulticaster.addApplicationListener(applicationListener);
59
            addToMap(o, applicationListener);
60

  
61
        }
62
    }
63

  
64
    @Override
65
    public void removeEventListeners(Object o){
66
        if(listenerMap.containsKey(o)){
67
            listenerMap.get(o).forEach(l -> applicationEventMulticaster.removeApplicationListener(l));
68
            listenerMap.remove(o);
69
        }
70
    }
71

  
72
    private void addToMap(Object o, ApplicationListener<?> applicationListener) {
73
        if(!listenerMap.containsKey(o)){
74
            listenerMap.put(o, new ArrayList<>());
75
        }
76
        listenerMap.get(o).add(applicationListener);
77
    }
78

  
79
    /**
80
     * {@inheritDoc}
81
     */
82
    @Override
83
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
84
        this.applicationContext = applicationContext;
85
    }
86

  
87
}
src/main/java/org/springframework/context/event/PojoEventListenerManager.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 org.springframework.context.event;
10

  
11
/**
12
 * @author a.kohlbecker
13
 * @since May 29, 2017
14
 *
15
 */
16
public interface PojoEventListenerManager {
17

  
18
    void removeEventListeners(Object o);
19

  
20
    void addEventListeners(Object o);
21

  
22
}
src/main/java/org/springframework/context/event/package.html
1
This package contains the PojoEventListenerManager which manages the event lsiterner methodfs in mvp popup presenter instances. 
2
Presenter instances are created in turn of the calls to NavigationManagerBean.findPopupView()
3
The PojoEventListenerManager creates ApplicationListener instances for each method annotated with @EventListner 
4
and adds them to the EventMulticaster.
5

  
6
These classes are locate in this spring package to allow the PojoEventListenerManager using the 
7
org.springframework.context.event.EventExpressionEvaluator class wich is otherwise not visible. 
8

  
9
see also https://dev.e-taxonomy.eu/redmine/issues/6673

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)