import com.vaadin.server.Page;
import com.vaadin.server.Page.UriFragmentChangedEvent;
import com.vaadin.server.Page.UriFragmentChangedListener;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CssLayout;
* and no error view is registered
*/
public void navigateTo(String navigationState) {
- String longestViewName = null;
- ViewProvider longestViewNameProvider = null;
+ ViewProvider longestViewNameProvider = getViewProvider(navigationState);
+ String longestViewName = longestViewNameProvider == null ? null
+ : longestViewNameProvider.getViewName(navigationState);
View viewWithLongestName = null;
- for (ViewProvider provider : providers) {
- String viewName = provider.getViewName(navigationState);
- if (null != viewName
- && (longestViewName == null || viewName.length() > longestViewName
- .length())) {
- longestViewName = viewName;
- longestViewNameProvider = provider;
- }
- }
+
if (longestViewName != null) {
viewWithLongestName = longestViewNameProvider
.getView(longestViewName);
parameters = navigationState
.substring(longestViewName.length() + 1);
}
- navigateTo(viewWithLongestName, longestViewName, parameters);
+ if (getCurrentView() == null
+ || !SharedUtil
+ .equals(getCurrentView(), viewWithLongestName)) {
+ navigateTo(viewWithLongestName, longestViewName, parameters);
+ } else {
+ updateNavigationState(new ViewChangeEvent(this,
+ getCurrentView(), viewWithLongestName, longestViewName,
+ parameters));
+ }
} else {
throw new IllegalArgumentException(
"Trying to navigate to an unknown state '"
}
/**
- * Destroys the navigator and cleans it up. The method detaches the
- * navigator from UI and removes all view change listeners.
+ * Get view provider that handles the given {@code state}.
+ *
+ * @param state
+ * state string
+ * @return suitable provider
+ */
+ private ViewProvider getViewProvider(String state) {
+ String longestViewName = null;
+ ViewProvider longestViewNameProvider = null;
+ for (ViewProvider provider : providers) {
+ String viewName = provider.getViewName(state);
+ if (null != viewName
+ && (longestViewName == null || viewName.length() > longestViewName
+ .length())) {
+ longestViewName = viewName;
+ longestViewNameProvider = provider;
+ }
+ }
+ return longestViewNameProvider;
+ }
+
+ /**
+ * Creates view change event for given {@code view}, {@code viewName} and
+ * {@code parameters}.
+ *
+ * @since
+ * @return view change event
*/
public void destroy() {
stateManager.setNavigator(null);
import org.easymock.IArgumentMatcher;
import org.easymock.IMocksControl;
import org.junit.Assert;
+import org.junit.Test;
import com.vaadin.navigator.NavigationStateManager;
import com.vaadin.navigator.Navigator;
// prepare mocks: what to expect
manager.setNavigator(EasyMock.anyObject(Navigator.class));
- EasyMock.expect(provider.getViewName("test1")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("test1")).andReturn("test1")
+ .times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("");
view1.enter(eventParametersEqual(""));
manager.setState("test1");
EasyMock.expect(manager.getState()).andReturn("test1");
- EasyMock.expect(provider.getViewName("test2/")).andReturn("test2");
+ EasyMock.expect(provider.getViewName("test2/")).andReturn("test2")
+ .times(2);
EasyMock.expect(provider.getView("test2")).andReturn(view2);
EasyMock.expect(manager.getState()).andReturn("test1");
view2.enter(eventParametersEqual(""));
EasyMock.expect(manager.getState()).andReturn("test2");
EasyMock.expect(provider.getViewName("test1/params"))
- .andReturn("test1");
+ .andReturn("test1").times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("test2");
view1.enter(eventParametersEqual("params"));
// prepare mocks: what to expect
manager.setNavigator(EasyMock.anyObject(Navigator.class));
- EasyMock.expect(provider.getViewName("test2")).andReturn("test2");
+ EasyMock.expect(provider.getViewName("test2")).andReturn("test2")
+ .times(2);
EasyMock.expect(provider.getView("test2")).andReturn(view2);
EasyMock.expect(manager.getState()).andReturn("view1");
view2.enter(eventParametersEqual(""));
display.showView(view2);
manager.setState("test2");
- EasyMock.expect(provider.getViewName("")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("")).andReturn("test1").times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("");
view1.enter(eventParametersEqual(""));
manager.setState("test1");
EasyMock.expect(provider.getViewName("test1/params"))
- .andReturn("test1");
+ .andReturn("test1").times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("test2");
view1.enter(eventParametersEqual("params"));
Navigator navigator = createNavigator(manager, display);
// prepare mocks: what to expect
- EasyMock.expect(provider.getViewName("test1")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("test1")).andReturn("test1")
+ .times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1,
"test1", "");
manager.setState("test1");
listener.addExpectedNavigatorViewChange(event1);
- EasyMock.expect(provider.getViewName("test2")).andReturn("test2");
+ EasyMock.expect(provider.getViewName("test2")).andReturn("test2")
+ .times(2);
EasyMock.expect(provider.getView("test2")).andReturn(view2);
ViewChangeEvent event2 = new ViewChangeEvent(navigator, view1, view2,
"test2", "");
// prepare mocks: what to expect
// first listener blocks first view change
- EasyMock.expect(provider.getViewName("test1")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("test1")).andReturn("test1")
+ .times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("");
ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1,
listener1.addExpectedIsViewChangeAllowed(event1, false);
// second listener blocks second view change
- EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1")
+ .times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("");
ViewChangeEvent event2 = new ViewChangeEvent(navigator, null, view1,
listener2.addExpectedIsViewChangeAllowed(event2, false);
// both listeners allow view change
- EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1");
+ EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1")
+ .times(2);
EasyMock.expect(provider.getView("test1")).andReturn(view1);
EasyMock.expect(manager.getState()).andReturn("");
ViewChangeEvent event3 = new ViewChangeEvent(navigator, null, view1,
listener2.addExpectedNavigatorViewChange(event3);
// both listeners allow view change from non-null view
- EasyMock.expect(provider.getViewName("test2")).andReturn("test2");
+ EasyMock.expect(provider.getViewName("test2")).andReturn("test2")
+ .times(2);
EasyMock.expect(provider.getView("test2")).andReturn(view2);
EasyMock.expect(manager.getState()).andReturn("view1");
ViewChangeEvent event4 = new ViewChangeEvent(navigator, view1, view2,
// Expected
}
}
+
+ @Test
+ public void testNavigateTo_navigateSameUriTwice_secondNavigationDoesNothing() {
+ NavigationStateManager manager = new NavigationStateManager() {
+
+ private String state;
+
+ @Override
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ @Override
+ public void setNavigator(Navigator navigator) {
+ }
+
+ @Override
+ public String getState() {
+ return state;
+ }
+ };
+
+ final String viewName = "view";
+
+ final View view = EasyMock.createMock(View.class);
+ ViewProvider provider = new ViewProvider() {
+
+ @Override
+ public String getViewName(String viewAndParameters) {
+ return viewName;
+ }
+
+ @Override
+ public View getView(String viewName) {
+ return view;
+ }
+
+ };
+
+ final int[] count = new int[] { 0 };
+ Navigator navigator = new Navigator(createMockUI(), manager,
+ EasyMock.createMock(ViewDisplay.class)) {
+ @Override
+ protected void navigateTo(View view, String viewName,
+ String parameters) {
+ count[0] = count[0] + 1;
+ super.navigateTo(view, viewName, parameters);
+ }
+ };
+ navigator.addProvider(provider);
+
+ // First time navigation
+ navigator.navigateTo(viewName);
+ Assert.assertEquals(1, count[0]);
+
+ // Second time navigation to the same view
+ navigator.navigateTo(viewName);
+ Assert.assertEquals(1, count[0]);
+ }
}