diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2012-09-20 14:07:14 +0300 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2012-09-20 14:08:51 +0300 |
commit | 2079e8525df2b12aa8f1103755c91ec2ab1fca95 (patch) | |
tree | 59a22f56d1096f4ef96bc8a969f0bf99c0f5e829 | |
parent | 6b28dc7bf41b8590fcab3d60afd5aa407f1f1401 (diff) | |
download | vaadin-framework-2079e8525df2b12aa8f1103755c91ec2ab1fca95.tar.gz vaadin-framework-2079e8525df2b12aa8f1103755c91ec2ab1fca95.zip |
Add a means to handle missing views in Navigator (#9060)
-rw-r--r-- | server/src/com/vaadin/navigator/Navigator.java | 90 | ||||
-rw-r--r-- | uitest/src/com/vaadin/tests/navigator/NavigatorTest.html | 55 | ||||
-rw-r--r-- | uitest/src/com/vaadin/tests/navigator/NavigatorTest.java | 11 |
3 files changed, 145 insertions, 11 deletions
diff --git a/server/src/com/vaadin/navigator/Navigator.java b/server/src/com/vaadin/navigator/Navigator.java index 257dfa208f..c9f6946ce5 100644 --- a/server/src/com/vaadin/navigator/Navigator.java +++ b/server/src/com/vaadin/navigator/Navigator.java @@ -112,7 +112,7 @@ public class Navigator implements Serializable { public String getState() { String fragment = page.getFragment(); if (fragment.startsWith("!")) { - return page.getFragment().substring(1); + return fragment.substring(1); } else { return ""; } @@ -338,6 +338,7 @@ public class Navigator implements Serializable { private View currentView = null; private List<ViewChangeListener> listeners = new LinkedList<ViewChangeListener>(); private List<ViewProvider> providers = new LinkedList<ViewProvider>(); + private ViewProvider errorProvider; /** * Creates a navigator that is tracking the active view using URI fragments @@ -443,6 +444,8 @@ public class Navigator implements Serializable { * * @param navigationState * view name and parameters + * + * @throws IllegalArgumentException */ public void navigateTo(String navigationState) { String longestViewName = null; @@ -459,6 +462,10 @@ public class Navigator implements Serializable { } } } + if (viewWithLongestName == null && errorProvider != null) { + longestViewName = errorProvider.getViewName(navigationState); + viewWithLongestName = errorProvider.getView(longestViewName); + } if (viewWithLongestName != null) { String parameters = ""; if (navigationState.length() > longestViewName.length() + 1) { @@ -466,8 +473,12 @@ public class Navigator implements Serializable { .substring(longestViewName.length() + 1); } navigateTo(viewWithLongestName, longestViewName, parameters); + } else { + throw new IllegalArgumentException( + "Trying to navigate to an unknown state '" + + navigationState + + "' and an error view provider not present"); } - // TODO if no view is found, what to do? } /** @@ -600,11 +611,11 @@ public class Navigator implements Serializable { } /** - * Register a view class for a view name. + * Registers a view class for a view name. * <p> * Registering another view with a name that is already registered * overwrites the old registration of the same type. - * + * <p> * A new view instance is created every time a view is requested. * * @param viewName @@ -676,9 +687,76 @@ public class Navigator implements Serializable { } /** - * Adds a listener for listening to changes of the active view. + * Registers a view class that is instantiated when no other view matches + * the navigation state. This implicitly sets an appropriate error view + * provider and overrides any previous + * {@link #setErrorProvider(ViewProvider)} call. + * + * @param viewClass + * The View class whose instance should be used as the error + * view. + */ + public void setErrorView(final Class<? extends View> viewClass) { + setErrorProvider(new ViewProvider() { + @Override + public View getView(String viewName) { + try { + return viewClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String getViewName(String navigationState) { + return navigationState; + } + }); + } + + /** + * Registers a view that is displayed when no other view matches the + * navigation state. This implicitly sets an appropriate error view provider + * and overrides any previous {@link #setErrorProvider(ViewProvider)} call. + * + * @param view + * The View that should be used as the error view. + */ + public void setErrorView(final View view) { + setErrorProvider(new ViewProvider() { + @Override + public View getView(String viewName) { + return view; + }; + + @Override + public String getViewName(String navigationState) { + return navigationState; + } + }); + } + + /** + * Registers a view provider that is queried for a view when no other view + * matches the navigation state. An error view provider should match any + * navigation state, but could return different views for different states. + * Its <code>getViewName(String navigationState)</code> should return + * <code>navigationState</code>. + * + * @param provider + */ + public void setErrorProvider(ViewProvider provider) { + errorProvider = provider; + } + + /** + * Listen to changes of the active view. * <p> - * The listener will get notified after the view has changed. + * Registered listeners are invoked in registration order before ( + * {@link ViewChangeListener#beforeViewChange(ViewChangeEvent) + * beforeViewChange()}) and after ( + * {@link ViewChangeListener#afterViewChange(ViewChangeEvent) + * afterViewChange()}) a view change occurs. * * @param listener * Listener to invoke during a view change. diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.html b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.html index 8c4e8f657b..030b30f37a 100644 --- a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.html +++ b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.html @@ -17,6 +17,11 @@ <td></td> </tr> <tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> + <td>1. Navigated to DefaultView with params</td> +</tr> +<tr> <td>click</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VButton[0]/domChild[0]/domChild[0]</td> <td></td> @@ -24,7 +29,7 @@ <tr> <td>assertText</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>1. Navigated to ListView with params</td> + <td>2. Navigated to ListView with params</td> </tr> <tr> <td>assertLocation</td> @@ -39,7 +44,7 @@ <tr> <td>assertText</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>2. Navigated to EditView with params</td> + <td>3. Navigated to EditView with params</td> </tr> <tr> <td>assertLocation</td> @@ -64,7 +69,7 @@ <tr> <td>assertText</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>3. Navigated to ListView with params param=value</td> + <td>4. Navigated to ListView with params param=value</td> </tr> <tr> <td>assertLocation</td> @@ -79,7 +84,7 @@ <tr> <td>assertText</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>4. Navigated to EditView with params param=value</td> + <td>5. Navigated to EditView with params param=value</td> </tr> <tr> <td>assertLocation</td> @@ -94,13 +99,53 @@ <tr> <td>assertText</td> <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> - <td>5. Prevent navigation to ForbiddenView</td> + <td>6. Prevent navigation to ForbiddenView</td> </tr> <tr> <td>assertLocation</td> <td>*#!edit/param=value</td> <td></td> </tr> +<tr> + <td>runScript</td> + <td>window.location.hash='!foo'</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> + <td>7. View 'foo' not found!</td> +</tr> +<tr> + <td>assertLocation</td> + <td>*#!foo</td> + <td></td> +</tr> +<tr> + <td>runScript</td> + <td>window.location.hash='foo'</td> + <td></td> +</tr> +<tr> + <td>pause</td> + <td>1000</td> + <td></td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestsnavigatorNavigatorTest::/VVerticalLayout[0]/VOrderedLayout$Slot[4]/VVerticalLayout[0]/VOrderedLayout$Slot[0]/VLabel[0]</td> + <td>8. Navigated to DefaultView with params</td> +</tr> +<tr> + <td>assertLocation</td> + <td>*#foo</td> + <td></td> +</tr> </tbody></table> </body> diff --git a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java index 4986bd21e6..a3f7ce9f5b 100644 --- a/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java +++ b/uitest/src/com/vaadin/tests/navigator/NavigatorTest.java @@ -74,6 +74,15 @@ public class NavigatorTest extends UI { } } + class ErrorView extends Label implements View { + @Override + public void enter(ViewChangeEvent event) { + log.log("View '" + event.getViewName() + "' not found!"); + setValue("Tried to navigate to " + event.getViewName() + + " but such a view could not be found :("); + } + } + class NaviListener implements ViewChangeListener { @Override @@ -114,6 +123,8 @@ public class NavigatorTest extends UI { navi.addViewChangeListener(new NaviListener()); + navi.setErrorView(new ErrorView()); + navi.navigate(); addComponent(new NaviButton("list")); |