Project

General

Profile

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

    
3
import java.util.Arrays;
4
import java.util.Collection;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.Stack;
10

    
11
import org.apache.commons.lang3.StringUtils;
12
import org.apache.log4j.Logger;
13
import org.springframework.beans.factory.annotation.Autowired;
14
import org.springframework.context.ApplicationContext;
15
import org.springframework.context.annotation.Lazy;
16
import org.vaadin.spring.events.EventBus;
17
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
18

    
19
import com.vaadin.navigator.ViewChangeListener;
20
import com.vaadin.navigator.ViewDisplay;
21
import com.vaadin.server.Sizeable.Unit;
22
import com.vaadin.spring.annotation.SpringView;
23
import com.vaadin.spring.annotation.UIScope;
24
import com.vaadin.spring.navigator.SpringNavigator;
25
import com.vaadin.spring.navigator.SpringViewProvider;
26
import com.vaadin.ui.UI;
27
import com.vaadin.ui.Window;
28

    
29
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.EditorActionContext;
30
import eu.etaxonomy.cdm.vaadin.security.PermissionDebugUtils;
31
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
32
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
33
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
34
import eu.etaxonomy.vaadin.mvp.ApplicationView;
35
import eu.etaxonomy.vaadin.ui.UIInitializedEvent;
36
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
37
import eu.etaxonomy.vaadin.ui.view.PopEditorOpenedEvent;
38
import eu.etaxonomy.vaadin.ui.view.PopupView;
39

    
40
@UIScope
41
public class NavigationManagerBean extends SpringNavigator implements NavigationManager {
42

    
43
	private static final long serialVersionUID = 6599898650948333853L;
44

    
45
	private final static Logger logger = Logger.getLogger(NavigationManagerBean.class);
46

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

    
54
	@Autowired
55
	private SpringViewProvider viewProvider;
56

    
57
	@Autowired
58
	private List<ViewChangeListener> viewChangeListeners;
59

    
60
	@Autowired
61
	protected ApplicationContext applicationContext;
62

    
63
	protected EventBus.UIEventBus uiEventBus;
64

    
65
    @Autowired
66
    protected void setViewEventBus(EventBus.UIEventBus uiEventBus){
67
        this.uiEventBus = uiEventBus;
68
        uiEventBus.subscribe(this);
69
    }
70

    
71

    
72
	/**
73
	 * This reference will cause the scoped UserHelper being initialized
74
	 * It is not used in this class but attaches itself to the vaadin session
75
	 * from where it will be accessible via UserHelper.fromSession()
76
	 */
77
	@Autowired
78
    private UserHelper userHelper;
79

    
80
    /**
81
     * This reference will cause the scoped PermissionDebugUtils being initialized.
82
     * It is not used in this class but attaches itself to the vaadin session
83
     * from where it will be accessible via UserHelper.fromSession()
84
     *
85
     * <b>NOTE:</b> PermissionDebugUtils is only available if the spring profile "debug" is active,
86
     * See
87
     */
88
    @Autowired(required=false)
89
    private PermissionDebugUtils permissionDebugUtils;
90

    
91
	private Map<PopupView, Window> popupMap;
92

    
93
	private String defaultViewName = null;
94

    
95
    /*
96
     * Why UriFragmentManager must be initialized lazily:
97
     *
98
     * when the SpringVaadinServlet usually is being instantiated the ServletUIInitHandler(UIInitHandler).getBrowserDetailsUI(VaadinRequest, VaadinSession) method is called which will
99
     * 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
100
     * via Page.getCurrent() which is used in the UriFragmentManager constructor. The NavigationManagerBean is initialized with the WebapplicationContext, that is when the current ui is
101
     * not yet available, therefore the UriFragmentManager must be initialized lazily.
102
     */
103
    @Autowired
104
    @Lazy
105
	private UriFragmentManager uriFragmentManager;
106

    
107

    
108
//	public void setUriFragmentManager(UriFragmentManager uriFragmentManager) {
109
//	    this.uriFragmentManager = uriFragmentManager;
110
//	}
111

    
112

    
113
	public NavigationManagerBean() {
114
	    popupMap = new HashMap<>();
115
	}
116

    
117
	private Collection<PopupView> popupViews = new HashSet<>();
118

    
119
//	@Lazy
120
//    @Autowired(required=false)
121
//    private void popUpViews(Collection<PopupView> popupViews){
122
//        this.popupViews = popupViews;
123
//        // popupViews.forEach(view -> this.popupViews.put(view.getClass(), view));
124
//    }
125

    
126
    private <P extends PopupView> P findPopupView(Class<P> type){
127
        P viewBean = applicationContext.getBean(type);
128
        if(viewBean == null){
129
            throw new NullPointerException("no popup-view bean of type " + type.getName() + " found");
130
        }
131
        return viewBean;
132
        // return popupViews.stream().filter(p -> p.getClass().equals(type)).findFirst();
133
    }
134

    
135
	@EventBusListenerMethod
136
	protected void onUIInitialized(UIInitializedEvent e) {
137
		init(UI.getCurrent(), uriFragmentManager, viewDisplay);
138
		addProvider(viewProvider);
139
		viewChangeListeners.forEach(vcl -> addViewChangeListener(vcl));
140
	}
141

    
142
	public void navigateTo(String navigationState, boolean fireNavigationEvent) {
143
	    if(StringUtils.isEmpty(navigationState)){
144
            navigationState = defaultViewName;
145
        }
146
		if (fireNavigationEvent) {
147
			navigateTo(navigationState);
148
		} else {
149
			super.navigateTo(navigationState);
150
		}
151
	}
152

    
153
	@Override
154
	public void navigateTo(String navigationState) {
155
	    if(StringUtils.isEmpty(navigationState)){
156
	        navigationState = defaultViewName;
157
	    }
158
		super.navigateTo(navigationState);
159
		//eventBus.publishEvent(new NavigationEvent(navigationState));
160
	}
161

    
162
	@EventBusListenerMethod
163
	protected void onNavigationEvent(NavigationEvent e) {
164
		navigateTo(e.getViewName(), false);
165
	}
166

    
167
	@Override
168
	public <T extends PopupView> T showInPopup(Class<T> popupType, ApplicationView parentView) {
169

    
170
	    PopupView popupView =  findPopupView(popupType);
171

    
172
	    if(AbstractPopupEditor.class.isAssignableFrom(popupView.getClass())){
173
	        if(parentView instanceof AbstractPopupEditor){
174
	            // retain the chain of EditorActionContexts when starting a new pupupEditor
175
	            Stack<EditorActionContext> parentEditorActionContext = ((AbstractPopupEditor)parentView).getEditorActionContext();
176
	            ((AbstractPopupEditor)popupView).setParentEditorActionContext(parentEditorActionContext);
177
	        }
178
	    }
179

    
180

    
181
		Window window = new Window();
182
		window.setCaption(popupView.getWindowCaption());
183
		window.center();
184
		window.setResizable(popupView.isResizable());
185
		// due to issue #6673 (https://dev.e-taxonomy.eu/redmine/issues/6673) popup editors must be modal!
186
		//window.setModal(popupView.isModal());
187
		window.setModal(true);
188
		window.setCaptionAsHtml(popupView.isWindowCaptionAsHtml());
189
		window.setWidth(popupView.getWindowPixelWidth(), Unit.PIXELS);
190
		// setting 100% as default height. If the height
191
		// would be undefined the window, will fit the size of
192
		// the content and will sometimes exceed the height of the
193
		// main window and will not get a scroll bar in this situation.
194
		// see #6843
195
		window.setHeight("100%");
196
		window.setContent(popupView.asComponent());
197
		// TODO need to disallow pressing the close [x] button:
198
		// since window.addCloseListener(e -> popupView.cancel()); will
199
		// cause sending cancel events even if save has been clicked
200
		window.setClosable(false);
201
		UI.getCurrent().addWindow(window);
202
		popupView.viewEntered();
203
		popupView.focusFirst();
204
		uiEventBus.publish(this, new PopEditorOpenedEvent(this, popupView));
205

    
206
		popupMap.put(popupView, window);
207

    
208
		return (T) popupView;
209
	}
210

    
211
    @EventBusListenerMethod
212
	protected void onDoneWithTheEditor(DoneWithPopupEvent e) {
213

    
214
		PopupView popup = e.getPopup();
215
        Window window = popupMap.get(popup);
216
		if (window != null) {
217
			window.close();
218
			popupMap.remove(popup);
219
		}
220
		if(AbstractPopupEditor.class.isAssignableFrom(popup.getClass())){
221
		    ((AbstractPopupEditor)popup).presenter().unsubscribeFromEventBuses();
222
		}
223

    
224
	}
225

    
226
    /**
227
     * {@inheritDoc}
228
     */
229
    @Override
230
    public void reloadCurrentView() {
231
        if(logger.isTraceEnabled()){
232
            logger.trace("reloading " + getState());
233
        }
234
        navigateTo(getState(), false);
235
    }
236

    
237
    /**
238
     * This method requires that the {@SpringView} annotation is used to ser the name of the <code>View</code>.
239
     *
240
     * @return the current view name or <code>null</code>
241
     */
242
    @Override
243
    public String getCurrentViewName() {
244
        if(getCurrentView() != null){
245
            SpringView springViewAnnotation = getCurrentView().getClass().getAnnotation(SpringView.class);
246
            if(springViewAnnotation != null){
247
                return springViewAnnotation.name();
248
            }
249
        }
250
        return null;
251
    }
252

    
253
    @Override
254
    public List<String> getCurrentViewParameters(){
255
        String substate = getState();
256
        String currentViewName = getCurrentViewName();
257
        if(currentViewName != null){
258
            substate = substate.replaceAll("^" + currentViewName + "/?", "");
259

    
260
        }
261
        return Arrays.asList(substate.split("/"));
262
    }
263

    
264
    /**
265
     * {@inheritDoc}
266
     */
267
    @Override
268
    public List<AbstractEditorPresenter<?, ?>> getPopupEditorPresenters() {
269
        // TODO Auto-generated method stub
270
        return null;
271
    }
272

    
273

    
274
    /**
275
     * @return the defaultViewName
276
     */
277
    public String getDefaultViewName() {
278
        return defaultViewName;
279
    }
280

    
281

    
282
    /**
283
     * @param defaultViewName the defaultViewName to set
284
     */
285
    public void setDefaultViewName(String defaultViewName) {
286
        this.defaultViewName = defaultViewName;
287
    }
288

    
289
    public void setViewDisplay(ViewDisplay viewDisplay){
290
        this.viewDisplay = viewDisplay;
291
    }
292
}
(4-4/7)