Project

General

Profile

Download (9.73 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.vaadin.ui.navigation;
2

    
3
import java.util.Arrays;
4
import java.util.List;
5
import java.util.Stack;
6

    
7
import org.apache.commons.lang3.StringUtils;
8
import org.apache.log4j.Logger;
9
import org.springframework.beans.factory.DisposableBean;
10
import org.springframework.beans.factory.annotation.Autowired;
11
import org.springframework.context.ApplicationContext;
12
import org.springframework.context.annotation.Lazy;
13
import org.vaadin.spring.events.EventBus;
14
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
15

    
16
import com.vaadin.navigator.ViewChangeListener;
17
import com.vaadin.navigator.ViewDisplay;
18
import com.vaadin.spring.annotation.SpringView;
19
import com.vaadin.spring.annotation.UIScope;
20
import com.vaadin.spring.navigator.SpringNavigator;
21
import com.vaadin.spring.navigator.SpringViewProvider;
22
import com.vaadin.ui.Field;
23
import com.vaadin.ui.UI;
24
import com.vaadin.ui.Window;
25

    
26
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.EditorActionContext;
27
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
28
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
29
import eu.etaxonomy.vaadin.mvp.ApplicationView;
30
import eu.etaxonomy.vaadin.ui.UIInitializedEvent;
31
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
32
import eu.etaxonomy.vaadin.ui.view.PopEditorOpenedEvent;
33
import eu.etaxonomy.vaadin.ui.view.PopupView;
34

    
35
@UIScope
36
public class NavigationManagerBean extends SpringNavigator implements NavigationManager {
37

    
38
	private static final long serialVersionUID = 6599898650948333853L;
39

    
40
	private final static Logger logger = Logger.getLogger(NavigationManagerBean.class);
41

    
42
	// injecting the viewDisplay as spring bean causes problems with older cdm vaadin code
43
	// SingleComponentContainerViewDisplay for example can't be used
44
	// the viewDisplay should be configurable per UI therefore it seems more elegant to
45
	// let the UI pass the viewDisplay to the Navigator
46
//	@Autowired
47
	private ViewDisplay viewDisplay;
48

    
49
	@Autowired
50
	private SpringViewProvider viewProvider;
51

    
52
	@Autowired
53
	private List<ViewChangeListener> viewChangeListeners;
54

    
55
	@Autowired
56
	protected ApplicationContext applicationContext;
57

    
58
	protected EventBus.UIEventBus uiEventBus;
59

    
60
    @Autowired
61
    protected void setViewEventBus(EventBus.UIEventBus uiEventBus){
62
        this.uiEventBus = uiEventBus;
63
        uiEventBus.subscribe(this);
64
    }
65

    
66
//    /**
67
//     * This reference will cause the scoped PermissionDebugUtils being initialized.
68
//     * It is not used in this class but attaches itself to the vaadin session
69
//     * from where it will be accessible via VaadinUserHelper.fromSession()
70
//     *
71
//     * <b>NOTE:</b> PermissionDebugUtils is only available if the spring profile "debug" is active,
72
//     * See
73
//     */
74
//    @Autowired(required=false)
75
//    private PermissionDebugUtils permissionDebugUtils;
76

    
77
	private PopupViewRegistration popupViewRegistration;
78

    
79
	private String defaultViewName = null;
80

    
81
    /*
82
     * Why UriFragmentManager must be initialized lazily:
83
     *
84
     * when the SpringVaadinServlet usually is being instantiated the ServletUIInitHandler(UIInitHandler).getBrowserDetailsUI(VaadinRequest, VaadinSession) method is called which will
85
     * first cause the WebapplicationContext being created. Once this is done the initialization of the UI classes is completed. This means that the UI classes are not readily available
86
     * via Page.getCurrent() which is used in the UriFragmentManager constructor. The NavigationManagerBean is initialized with the WebapplicationContext, that is when the current ui is
87
     * not yet available, therefore the UriFragmentManager must be initialized lazily.
88
     */
89
    @Autowired
90
    @Lazy
91
	private UriFragmentManager uriFragmentManager;
92

    
93

    
94
//	public void setUriFragmentManager(UriFragmentManager uriFragmentManager) {
95
//	    this.uriFragmentManager = uriFragmentManager;
96
//	}
97

    
98

    
99
	public NavigationManagerBean() {
100
	    popupViewRegistration = new PopupViewRegistration();
101
	}
102

    
103
//	private Collection<PopupView> popupViews = new HashSet<>();
104
//	@Lazy
105
//    @Autowired(required=false)
106
//    private void popUpViews(Collection<PopupView> popupViews){
107
//        this.popupViews = popupViews;
108
//        // popupViews.forEach(view -> this.popupViews.put(view.getClass(), view));
109
//    }
110

    
111
    private <P extends PopupView> P findPopupView(Class<P> type){
112
        P viewBean = applicationContext.getBean(type);
113
        if(viewBean == null){
114
            throw new NullPointerException("no popup-view bean of type " + type.getName() + " found");
115
        }
116
        return viewBean;
117
        // return popupViews.stream().filter(p -> p.getClass().equals(type)).findFirst();
118
    }
119

    
120
	@EventBusListenerMethod
121
	protected void onUIInitialized(UIInitializedEvent e) {
122
		init(UI.getCurrent(), uriFragmentManager, viewDisplay);
123
		addProvider(viewProvider);
124
		viewChangeListeners.forEach(vcl -> addViewChangeListener(vcl));
125
	}
126

    
127
	public void navigateTo(String navigationState, boolean fireNavigationEvent) {
128
	    if(StringUtils.isEmpty(navigationState)){
129
            navigationState = defaultViewName;
130
        }
131
		if (fireNavigationEvent) {
132
			navigateTo(navigationState);
133
		} else {
134
			super.navigateTo(navigationState);
135
		}
136
	}
137

    
138
	@Override
139
	public void navigateTo(String navigationState) {
140
	    if(StringUtils.isEmpty(navigationState)){
141
	        navigationState = defaultViewName;
142
	    }
143
		super.navigateTo(navigationState);
144
		//eventBus.publishEvent(new NavigationEvent(navigationState));
145
	}
146

    
147
	@EventBusListenerMethod
148
	protected void onNavigationEvent(NavigationEvent e) {
149
		navigateTo(e.getViewName(), false);
150
	}
151

    
152
	@Override
153
	public <T extends PopupView> T showInPopup(Class<T> popupType, ApplicationView parentView, Field<?> targetField) {
154

    
155
	    PopupView popupView =  findPopupView(popupType);
156

    
157
	    if(AbstractPopupEditor.class.isAssignableFrom(popupView.getClass())){
158
	        if(parentView instanceof AbstractPopupEditor){
159
	            // retain the chain of EditorActionContexts when starting a new pupupEditor
160
	            Stack<EditorActionContext> parentEditorActionContext = ((AbstractPopupEditor)parentView).getEditorActionContext();
161
	            ((AbstractPopupEditor)popupView).setParentEditorActionContext(parentEditorActionContext);
162
	        }
163
	    }
164

    
165
		Window window = new Window();
166
		window.setCaption(popupView.getWindowCaption());
167
		window.center();
168
		window.setResizable(popupView.isResizable());
169
		// due to issue #6673 (https://dev.e-taxonomy.eu/redmine/issues/6673) popup editors must be modal!
170
		//window.setModal(popupView.isModal());
171
		window.setModal(true);
172
		window.setCaptionAsHtml(popupView.isWindowCaptionAsHtml());
173
		window.setWidth(popupView.getWindowWidth(), popupView.getWindowWidthUnit());
174
		window.setHeight(popupView.getWindowHeight(), popupView.getWindowHeightUnit());
175
		window.setContent(popupView.asComponent());
176
		// TODO need to disallow pressing the close [x] button:
177
		// since window.addCloseListener(e -> popupView.cancel()); will
178
		// cause sending cancel events even if save has been clicked
179
		window.setClosable(popupView.isClosable());
180
		UI.getCurrent().addWindow(window);
181
		popupView.viewEntered();
182
		popupView.focusFirst();
183
		uiEventBus.publish(this, new PopEditorOpenedEvent(this, popupView));
184

    
185
		popupViewRegistration.put(window, parentView, popupView, targetField);
186

    
187
		return (T) popupView;
188
	}
189

    
190
	@Override
191
    public Field<?> targetFieldOf(PopupView popupView){
192
	    return popupViewRegistration.get(popupView);
193
	}
194

    
195
    @EventBusListenerMethod
196
	protected void onDoneWithTheEditor(DoneWithPopupEvent event) {
197

    
198
		PopupView popup = event.getPopup();
199
		if(DisposableBean.class.isAssignableFrom(popup.getClass())){
200
		    try {
201
                ((DisposableBean)popup).destroy();
202
            } catch (Exception e) {
203
                logger.error(e);
204
            }
205
		}
206
        Window window = popupViewRegistration.getWindow(popup);
207
		if (window != null) {
208
			window.close();
209
			popupViewRegistration.remove(popup);
210
		}
211
		if(AbstractPopupEditor.class.isAssignableFrom(popup.getClass())){
212
		    ((AbstractPopupEditor)popup).presenter().unsubscribeFromEventBuses();
213
		}
214

    
215
	}
216

    
217
    /**
218
     * {@inheritDoc}
219
     */
220
    @Override
221
    public void reloadCurrentView() {
222
        if(logger.isTraceEnabled()){
223
            logger.trace("reloading " + getState());
224
        }
225
        navigateTo(getState(), false);
226
    }
227

    
228
    /**
229
     * This method requires that the {@SpringView} annotation is used to set the name of the <code>View</code>.
230
     *
231
     * @return the current view name or <code>null</code>
232
     */
233
    @Override
234
    public String getCurrentViewName() {
235
        if(getCurrentView() != null){
236
            SpringView springViewAnnotation = getCurrentView().getClass().getAnnotation(SpringView.class);
237
            if(springViewAnnotation != null){
238
                return springViewAnnotation.name();
239
            }
240
        }
241
        return null;
242
    }
243

    
244
    @Override
245
    public List<String> getCurrentViewParameters(){
246
        String substate = getState();
247
        String currentViewName = getCurrentViewName();
248
        if(currentViewName != null){
249
            substate = substate.replaceAll("^" + currentViewName + "/?", "");
250

    
251
        }
252
        return Arrays.asList(substate.split("/"));
253
    }
254

    
255
    /**
256
     * {@inheritDoc}
257
     */
258
    @Override
259
    public List<AbstractEditorPresenter<?, ?>> getPopupEditorPresenters() {
260
        // TODO Auto-generated method stub
261
        return null;
262
    }
263

    
264

    
265
    /**
266
     * @return the defaultViewName
267
     */
268
    public String getDefaultViewName() {
269
        return defaultViewName;
270
    }
271

    
272

    
273
    /**
274
     * @param defaultViewName the defaultViewName to set
275
     */
276
    public void setDefaultViewName(String defaultViewName) {
277
        this.defaultViewName = defaultViewName;
278
    }
279

    
280
    public void setViewDisplay(ViewDisplay viewDisplay){
281
        this.viewDisplay = viewDisplay;
282
    }
283

    
284
    /**
285
     * {@inheritDoc}
286
     */
287
    @Override
288
    public void destroy() {
289
        super.destroy();
290
        uiEventBus.unsubscribe(this);
291
    }
292

    
293

    
294
}
(4-4/8)