Project

General

Profile

Download (9.81 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
		popupViewRegistration.removeOrphan();
137
	}
138

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

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

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

    
157
	    PopupView popupView =  findPopupView(popupType);
158

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

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

    
187
		popupViewRegistration.put(window, parentView, popupView, targetField);
188

    
189
		return (T) popupView;
190
	}
191

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

    
197
    @EventBusListenerMethod
198
	protected void onDoneWithTheEditor(DoneWithPopupEvent event) {
199

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

    
217
	}
218

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

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

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

    
253
        }
254
        return Arrays.asList(substate.split("/"));
255
    }
256

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

    
266

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

    
274

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

    
282
    public void setViewDisplay(ViewDisplay viewDisplay){
283
        this.viewDisplay = viewDisplay;
284
    }
285

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

    
295

    
296
}
(4-4/8)