Project

General

Profile

Download (7.66 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.vaadin.mvp;
2

    
3
import java.io.Serializable;
4

    
5
import org.apache.log4j.Logger;
6
import org.hibernate.Session;
7
import org.hibernate.engine.internal.StatefulPersistenceContext;
8
import org.hibernate.engine.spi.SessionImplementor;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.beans.factory.annotation.Qualifier;
11
import org.springframework.security.core.context.SecurityContext;
12
import org.springframework.security.core.context.SecurityContextHolder;
13
import org.vaadin.spring.events.EventBus;
14

    
15
import com.vaadin.ui.Field;
16

    
17
import eu.etaxonomy.cdm.api.application.CdmRepository;
18
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction;
19
import eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent;
20
import eu.etaxonomy.vaadin.ui.navigation.NavigationManager;
21
import eu.etaxonomy.vaadin.ui.view.PopupView;
22

    
23
/**
24
 * AbstractPresenter is the base class of all presenter components. Presenter's
25
 * role is to govern the view and control the complex UI logic based on
26
 * notifications presenter receives from its view.
27
 *
28
 * @author Peter / Vaadin
29
 *
30
 * @param <V>
31
 *            type of the view this presenter governs
32
 */
33
public abstract class AbstractPresenter<V extends ApplicationView> implements Serializable {
34

    
35

    
36
    private static final long serialVersionUID = 5260910510283481832L;
37

    
38
    public static final Logger logger = Logger.getLogger(AbstractPresenter.class);
39

    
40
	private V view;
41

    
42
	protected V getView() {
43
	    if(view == null){
44
            Logger.getLogger(this.getClass()).warn("CDM-VAADIN#6562: presenter " + toString() + " without view.");
45
        }
46
		return view;
47
	}
48

    
49
	@Autowired
50
	@Qualifier("cdmRepository")
51
	private CdmRepository repo;
52

    
53
	@Autowired
54
	private NavigationManager navigationManager;
55

    
56
    protected EventBus.ViewEventBus viewEventBus;
57

    
58
    @Autowired
59
    protected void setViewEventBus(EventBus.ViewEventBus viewEventBus){
60
        this.viewEventBus = viewEventBus;
61
        eventViewBusSubscription(viewEventBus);
62
    }
63

    
64
    /**
65
     * Override if needed, e.g. to skip subscription
66
     *
67
     * @param viewEventBus
68
     */
69
    protected void eventViewBusSubscription(EventBus.ViewEventBus viewEventBus){
70
            viewEventBus.subscribe(this);
71
    }
72

    
73
    public void unsubscribeFromEventBuses(){
74
        viewEventBus.unsubscribe(this);
75
    }
76

    
77

    
78
	//	protected DefaultTransactionDefinition definition = null;
79

    
80
    //	protected TransactionDefinition getTransactionDefinition(){
81
    //	    if(definition == null){
82
    //    	    definition = new DefaultTransactionDefinition();
83
    //    	    definition.setReadOnly(true);
84
    //	    }
85
    //	    return definition;
86
    //	}
87

    
88

    
89
	/**
90
	 * @return the repo
91
	 */
92
	public CdmRepository getRepo() {
93
	    return repo;
94
	}
95

    
96
	/**
97
     * @return
98
     *
99
     * FIXME is it ok to use the SecurityContextHolder or do we need to hold the context in the vaadin session?
100
     */
101
    protected SecurityContext currentSecurityContext() {
102
        return SecurityContextHolder.getContext();
103
    }
104

    
105
    /**
106
     * @return
107
     */
108
    protected Session getSession() {
109
        Session session = getRepo().getSession();
110
        if(logger.isTraceEnabled()){
111
            if(session.isOpen()){
112
                logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() +", persistenceContext: " + ((SessionImplementor)session).getPersistenceContext() + " - " + session.toString());
113
            }  else {
114
                logger.trace(this._toString() + ".getSession() - session:" + session.hashCode() +"  is closed ");
115
            }
116
        }
117
        return session;
118
    }
119

    
120
    protected String _toString(){
121
        return this.getClass().getSimpleName() + "@" + this.hashCode();
122
    }
123

    
124
	/**
125
	 * Notifies the presenter that its view is initialized so that presenter can
126
	 * start its own initialization if required.
127
	 *
128
	 * @param view
129
	 */
130
	protected void init(V view) {
131
	    logger.trace(String.format("Presenter %s init()", _toString()));
132
		this.view = view;
133
		onPresenterReady();
134
	}
135

    
136

    
137
    /**
138
	 * Extending classes should overwrite this method in order to perform logic
139
	 * after presenter has finished initializing.
140
	 *
141
	 * At this point in the life cycle of the MVP the {@link AbstractView#initContent() initContent()}
142
	 * method has been executed already.
143
	 */
144
	protected void onPresenterReady() {
145
	    logger.trace(String.format("Presenter %s ready", _toString()));
146
	}
147

    
148
    /**
149
     * @return
150
     */
151
    private StatefulPersistenceContext getPersitenceContext() {
152
        return (StatefulPersistenceContext)((SessionImplementor)getSession()).getPersistenceContext();
153
    }
154

    
155
    public final void onViewEnter() {
156
	    logger.trace(String.format("%s onViewEnter()", _toString()));
157
	    handleViewEntered();
158
	}
159

    
160
	public void onViewExit() {
161
	    logger.trace(String.format("%s onViewExit()", _toString()));
162
	    handleViewExit();
163
	}
164

    
165
	/**
166
	 * Extending classes should overwrite this method to react to the event when
167
	 * user has navigated into the view that this presenter governs.
168
	 * For implementations of {@link AbstractPopupEditor AbstractPopupEditors} this is usually
169
	 * called before the data item has been bound. This order is guaranteed since popup editors
170
	 * are managed through the {@link NavigationManagerBean}
171
	 */
172
	public void handleViewEntered() {
173
	}
174

    
175
    /**
176
     * Extending classes may overwrite this method to react to
177
     * the event when user leaves the view that this presenter
178
     * governs. This method is executed before un-binding and closing the
179
     * conversation holder.
180
     */
181
    public void handleViewExit() {
182
    }
183

    
184
    /**
185
     * @return the navigationManager
186
     */
187
    public NavigationManager getNavigationManager() {
188
        return navigationManager;
189
    }
190

    
191
    /**
192
     * @param repo the repo to set
193
     */
194
    protected void setRepo(CdmRepository repo) {
195
        this.repo = repo;
196
    }
197

    
198
    /**
199
     * @param navigationManager the navigationManager to set
200
     */
201
    protected void setNavigationManager(NavigationManager navigationManager) {
202
        this.navigationManager = navigationManager;
203
    }
204

    
205
    protected boolean checkFromOwnView(AbstractEditorAction event) {
206
        return getView() != null && getView() == event.getSourceView();
207
    }
208

    
209
    /**
210
     * Opens a new PopView or editor of the type <code>popupViewClass</code> for the current view.
211
     * If the <code>event</code> is not null and if it contains a target field the newly created editor
212
     * will be registered with this field as target. Once the popup editor is being saved a
213
     * {@link eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent} will be emitted which will hold a
214
     * reference to the popup editor in the {@link eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent#getSourceView() sourceView}
215
     * property. By this reference the target field can be retrieved in editor presenters via the method
216
     * {@link AbstractEditorPresenter#boundTargetField(PopupView)}:
217
     * <p>
218
     * {@code
219
     *   BoundField targetField = boundTargetField(entityChangeEvent.getSourceView())
220
     * }
221
     * </p>
222
     * In case the target field is bound to a bean property the propertyId is available in the {@link BoundField}
223
     * object and can be used to decide on which bean property to update with the data saved in the popup editor or to
224
     * act in any other appropriate way.
225
     *
226
     * @param popupViewClass
227
     * @param event
228
     * @return
229
     */
230
    protected <T extends PopupView> T openPopupEditor(Class<T> popupViewClass, AbstractEditorAction<?> event) {
231
        Field<?> targetField = event != null? event.getTarget(): null;
232
        return getNavigationManager().showInPopup(popupViewClass, getView(), targetField);
233
    }
234

    
235
    protected boolean isFromOwnView(EntityChangeEvent event) {
236
        return event.getSourceView() != null && event.getSourceView().equals(getView());
237
    }
238

    
239
}
(8-8/13)