1 package eu
.etaxonomy
.vaadin
.mvp
;
3 import java
.io
.Serializable
;
5 import org
.apache
.log4j
.Logger
;
6 import org
.springframework
.beans
.factory
.DisposableBean
;
7 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
8 import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
9 import org
.springframework
.security
.core
.context
.SecurityContext
;
10 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
11 import org
.vaadin
.spring
.events
.EventBus
;
13 import com
.vaadin
.ui
.Field
;
15 import eu
.etaxonomy
.cdm
.api
.application
.CdmRepository
;
16 import eu
.etaxonomy
.cdm
.vaadin
.event
.AbstractEditorAction
;
17 import eu
.etaxonomy
.cdm
.vaadin
.event
.EntityChangeEvent
;
18 import eu
.etaxonomy
.vaadin
.ui
.navigation
.NavigationManager
;
19 import eu
.etaxonomy
.vaadin
.ui
.view
.PopupView
;
22 * AbstractPresenter is the base class of all presenter components. Presenter's
23 * role is to govern the view and control the complex UI logic based on
24 * notifications presenter receives from its view.
26 * @author Peter / Vaadin
29 * type of the view this presenter governs
31 public abstract class AbstractPresenter
<V
extends ApplicationView
> implements Serializable
, DisposableBean
{
34 private static final long serialVersionUID
= 5260910510283481832L;
36 public static final Logger logger
= Logger
.getLogger(AbstractPresenter
.class);
40 protected V
getView() {
42 Logger
.getLogger(this.getClass()).warn("CDM-VAADIN#6562: presenter " + toString() + " without view.");
48 @Qualifier("cdmRepository")
49 private CdmRepository repo
;
52 private NavigationManager navigationManager
;
54 protected EventBus
.ViewEventBus viewEventBus
;
57 protected void setViewEventBus(EventBus
.ViewEventBus viewEventBus
){
58 this.viewEventBus
= viewEventBus
;
59 eventViewBusSubscription(viewEventBus
);
63 * Override if needed, e.g. to skip subscription
67 protected void eventViewBusSubscription(EventBus
.ViewEventBus viewEventBus
){
68 viewEventBus
.subscribe(this);
71 public void unsubscribeFromEventBuses(){
72 viewEventBus
.unsubscribe(this);
76 // protected DefaultTransactionDefinition definition = null;
78 // protected TransactionDefinition getTransactionDefinition(){
79 // if(definition == null){
80 // definition = new DefaultTransactionDefinition();
81 // definition.setReadOnly(true);
90 public CdmRepository
getRepo() {
97 * FIXME is it ok to use the SecurityContextHolder or do we need to hold the context in the vaadin session?
99 protected SecurityContext
currentSecurityContext() {
100 return SecurityContextHolder
.getContext();
104 protected String
_toString(){
105 return this.getClass().getSimpleName() + "@" + this.hashCode();
109 * Notifies the presenter that its view is initialized so that presenter can
110 * start its own initialization if required.
114 protected void init(V view
) {
115 logger
.trace(String
.format("Presenter %s init()", _toString()));
122 * Extending classes should overwrite this method in order to perform logic
123 * after presenter has finished initializing.
125 * At this point in the life cycle of the MVP the {@link AbstractView#initContent() initContent()}
126 * method has been executed already.
128 protected void onPresenterReady() {
129 logger
.trace(String
.format("Presenter %s ready", _toString()));
132 public final void onViewEnter() {
133 logger
.trace(String
.format("%s onViewEnter()", _toString()));
137 public void onViewExit() {
138 logger
.trace(String
.format("%s onViewExit()", _toString()));
143 * Extending classes should overwrite this method to react to the event when
144 * user has navigated into the view that this presenter governs.
145 * For implementations of {@link AbstractPopupEditor AbstractPopupEditors} this is usually
146 * called before the data item has been bound. This order is guaranteed since popup editors
147 * are managed through the {@link NavigationManagerBean}
149 public void handleViewEntered() {
150 // fist of all clear the session to wipe out any left overs from previous usage of the session
151 // this can happen if not all operations within a session are cleaned up correctly in
152 // turn of an exception
153 getRepo().clearSession();
157 * Extending classes may overwrite this method to react to
158 * the event when user leaves the view that this presenter
159 * governs. This method is executed before un-binding and closing the
160 * conversation holder.
162 public void handleViewExit() {
166 * @return the navigationManager
168 public NavigationManager
getNavigationManager() {
169 return navigationManager
;
173 * @param repo the repo to set
175 protected void setRepo(CdmRepository repo
) {
180 * @param navigationManager the navigationManager to set
182 protected void setNavigationManager(NavigationManager navigationManager
) {
183 this.navigationManager
= navigationManager
;
186 protected boolean checkFromOwnView(AbstractEditorAction event
) {
187 return getView() != null && getView() == event
.getSourceView();
191 * Opens a new PopView or editor of the type <code>popupViewClass</code> for the current view.
192 * If the <code>event</code> is not null and if it contains a target field the newly created editor
193 * will be registered with this field as target. Once the popup editor is being saved a
194 * {@link eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent} will be emitted which will hold a
195 * reference to the popup editor in the {@link eu.etaxonomy.cdm.vaadin.event.EntityChangeEvent#getSourceView() sourceView}
196 * property. By this reference the target field can be retrieved in editor presenters via the method
197 * {@link AbstractEditorPresenter#boundTargetField(PopupView)}:
200 * BoundField targetField = boundTargetField(entityChangeEvent.getSourceView())
203 * In case the target field is bound to a bean property the propertyId is available in the {@link BoundField}
204 * object and can be used to decide on which bean property to update with the data saved in the popup editor or to
205 * act in any other appropriate way.
207 * @param popupViewClass
211 protected <T
extends PopupView
> T
openPopupEditor(Class
<T
> popupViewClass
, AbstractEditorAction
<?
> event
) {
212 Field
<?
> targetField
= event
!= null? event
.getTarget(): null;
213 return getNavigationManager().showInPopup(popupViewClass
, getView(), targetField
);
216 protected boolean isFromOwnView(EntityChangeEvent event
) {
217 return event
.getSourceView() != null && event
.getSourceView().equals(getView());
221 public void destroy() throws Exception
{
222 unsubscribeFromEventBuses();