diff options
author | Denis Anisimov <denis@vaadin.com> | 2014-11-16 15:41:33 +0200 |
---|---|---|
committer | Teemu Suo-Anttila <teemusa@vaadin.com> | 2016-06-13 16:14:52 +0300 |
commit | 8117b2602a53486c543b7cd47033f01a366d78d7 (patch) | |
tree | fb07d9204daa2cadf51904942037129059faaa33 | |
parent | bf4ad03b203a6957ab10bd98ec1ac4e0d50b660a (diff) | |
download | vaadin-framework-8117b2602a53486c543b7cd47033f01a366d78d7.tar.gz vaadin-framework-8117b2602a53486c543b7cd47033f01a366d78d7.zip |
Provide a way to disallow navigation to the same state twice (#12107).
Change-Id: I831a02f26929cc7ec4dac5177cb68f84bd0bfc2b
-rw-r--r-- | server/src/main/java/com/vaadin/navigator/Navigator.java | 55 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java | 92 |
2 files changed, 121 insertions, 26 deletions
diff --git a/server/src/main/java/com/vaadin/navigator/Navigator.java b/server/src/main/java/com/vaadin/navigator/Navigator.java index 82e8de920a..390e252906 100644 --- a/server/src/main/java/com/vaadin/navigator/Navigator.java +++ b/server/src/main/java/com/vaadin/navigator/Navigator.java @@ -41,6 +41,7 @@ import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; 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; @@ -543,18 +544,11 @@ public class Navigator implements Serializable { * 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); @@ -570,7 +564,15 @@ public class Navigator implements Serializable { 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 '" @@ -986,8 +988,33 @@ public class Navigator implements Serializable { } /** - * 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); diff --git a/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java b/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java index 0eda1ed045..3b7ad0ae00 100644 --- a/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java +++ b/server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java @@ -318,7 +318,8 @@ public class NavigatorTest { // 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("")); @@ -326,7 +327,8 @@ public class NavigatorTest { 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("")); @@ -335,7 +337,7 @@ public class NavigatorTest { 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")); @@ -372,14 +374,15 @@ public class NavigatorTest { // 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("")); @@ -387,7 +390,7 @@ public class NavigatorTest { 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")); @@ -420,7 +423,8 @@ public class NavigatorTest { 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", ""); @@ -431,7 +435,8 @@ public class NavigatorTest { 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", ""); @@ -501,7 +506,8 @@ public class NavigatorTest { // 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, @@ -509,7 +515,8 @@ public class NavigatorTest { 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, @@ -518,7 +525,8 @@ public class NavigatorTest { 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, @@ -532,7 +540,8 @@ public class NavigatorTest { 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, @@ -837,4 +846,63 @@ public class NavigatorTest { fail("Should not be allowed to add a null view provider"); } + + @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]); + } } |