diff options
author | Peter Lehto <peter@vaadin.com> | 2017-06-13 12:41:36 +0300 |
---|---|---|
committer | Artur <artur@vaadin.com> | 2017-06-13 12:41:36 +0300 |
commit | cb1a2b99472faabba3596d673dbdbc377fb1628a (patch) | |
tree | 5d314656198c06b6411fce5a6b6a62214fa59197 /server | |
parent | 2f5e484a12f25d10ac6034d8ee9176b553b96c2d (diff) | |
download | vaadin-framework-cb1a2b99472faabba3596d673dbdbc377fb1628a.tar.gz vaadin-framework-cb1a2b99472faabba3596d673dbdbc377fb1628a.zip |
Add getStateParameterMap to Navigator to get parameters as a map (#9517)
Diffstat (limited to 'server')
-rw-r--r-- | server/src/main/java/com/vaadin/navigator/Navigator.java | 87 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/tests/server/navigator/NavigatorTest.java | 127 |
2 files changed, 188 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 2341479832..8b9e39b354 100644 --- a/server/src/main/java/com/vaadin/navigator/Navigator.java +++ b/server/src/main/java/com/vaadin/navigator/Navigator.java @@ -17,9 +17,13 @@ package com.vaadin.navigator; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Objects; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.Page; @@ -53,6 +57,11 @@ public class Navigator implements Serializable { // TODO investigate relationship with TouchKit navigation support + private static final String DEFAULT_VIEW_SEPARATOR = "/"; + + private static final String DEFAULT_STATE_PARAMETER_SEPARATOR = "&"; + private static final String DEFAULT_STATE_PARAMETER_KEY_VALUE_SEPARATOR = "="; + /** * Empty view component. */ @@ -340,23 +349,17 @@ public class Navigator implements Serializable { /** * The {@link UI} bound with the Navigator. - * - * @since 8.0.3 */ protected UI ui; /** * The {@link NavigationStateManager} that is used to get, listen to and * manipulate the navigation state used by the Navigator. - * - * @since 8.0.3 */ protected NavigationStateManager stateManager; /** * The {@link ViewDisplay} used by the Navigator. - * - * @since 8.0.3 */ protected ViewDisplay display; @@ -742,6 +745,76 @@ public class Navigator implements Serializable { } /** + * Returns the current navigation state reported by this Navigator's + * {@link NavigationStateManager} as Map<String, String> where each key + * represents a parameter in the state. + * + * Uses {@literal &} as parameter separator. If the state contains + * {@literal #!view/foo&bar=baz} then this method will return a map + * containing {@literal foo => ""} and {@literal bar => baz}. + * + * @return The parameters from the navigation state as a map + * @see #getStateParameterMap(String) + */ + public Map<String, String> getStateParameterMap() { + return getStateParameterMap(DEFAULT_STATE_PARAMETER_SEPARATOR); + } + + /** + * Returns the current navigation state reported by this Navigator's + * {@link NavigationStateManager} as Map<String, String> where each key + * represents a parameter in the state. The state parameter separator + * character needs to be specified with the separator. + * + * @param separator + * the string (typically one character) used to separate values + * from each other + * @return The parameters from the navigation state as a map + * @see #getStateParameterMap() + */ + public Map<String, String> getStateParameterMap(String separator) { + return parseStateParameterMap(Objects.requireNonNull(separator)); + } + + /** + * Parses the state parameter map using given separator String. + * + * @param separator + * the string (typically one character) used to separate values + * from each other + * @return The navigation state as Map<String, String>. + */ + protected Map<String, String> parseStateParameterMap(String separator) { + Map<String, String> parameterMap = new HashMap<>(); + if (getState() == null || getState().isEmpty()) { + return Collections.emptyMap(); + } + + String state = getState(); + int viewSeparatorLocation = state.indexOf(DEFAULT_VIEW_SEPARATOR); + + String parameterString; + if (viewSeparatorLocation == -1) { + parameterString = ""; + } else { + parameterString = state.substring(viewSeparatorLocation + 1, + state.length()); + } + if (parameterString.isEmpty()) { + return Collections.emptyMap(); + } + String[] parameters = parameterString.split(separator); + for (int i = 0; i < parameters.length; i++) { + String[] keyAndValue = parameters[i] + .split(DEFAULT_STATE_PARAMETER_KEY_VALUE_SEPARATOR); + parameterMap.put(keyAndValue[0], + keyAndValue.length > 1 ? keyAndValue[1] : ""); + } + + return parameterMap; + } + + /** * Return the {@link ViewDisplay} used by the navigator. * * @return the ViewDisplay used for displaying views @@ -993,8 +1066,6 @@ public class Navigator implements Serializable { * @param state * state string * @return suitable provider - * - * @since 8.0.3 */ protected ViewProvider getViewProvider(String state) { String longestViewName = 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 6991fd1b9e..022b388840 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 @@ -23,6 +23,8 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; import org.easymock.EasyMock; import org.easymock.IArgumentMatcher; @@ -51,6 +53,25 @@ import com.vaadin.ui.VerticalLayout; public class NavigatorTest { + private final class TestNavigationStateManager + implements 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; + } + } + // TODO test internal parameters (and absence of them) // TODO test listeners blocking navigation, multiple listeners @@ -854,24 +875,7 @@ public class NavigatorTest { @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; - } - }; + NavigationStateManager manager = new TestNavigationStateManager(); final String viewName = "view"; @@ -969,4 +973,91 @@ public class NavigatorTest { ((Label) ((HorizontalLayout) ui.getContent()).getComponent(0)) .getValue()); } + + @Test + public void parameterMap_noViewSeparator() { + Navigator navigator = createNavigatorWithState("fooview"); + Assert.assertTrue(navigator.getStateParameterMap().isEmpty()); + Assert.assertTrue(navigator.getStateParameterMap("foo").isEmpty()); + } + + @Test + public void parameterMap_noParameters() { + Navigator navigator = createNavigatorWithState("fooview/"); + Assert.assertTrue(navigator.getStateParameterMap().isEmpty()); + } + + @Test + public void parameterMap_oneParameterNoValue() { + Navigator navigator = createNavigatorWithState("fooview/bar"); + assertMap(navigator.getStateParameterMap(), entry("bar", "")); + } + + @Test + public void parameterMap_oneParameterNoValueButEquals() { + Navigator navigator = createNavigatorWithState("fooview/bar="); + assertMap(navigator.getStateParameterMap(), entry("bar", "")); + } + + @Test + public void parameterMap_oneParameterWithValue() { + Navigator navigator = createNavigatorWithState("fooview/bar=baz"); + assertMap(navigator.getStateParameterMap(), entry("bar", "baz")); + } + + @Test + public void parameterMap_twoParameters() { + Navigator navigator = createNavigatorWithState("fooview/foo=bar&baz"); + assertMap(navigator.getStateParameterMap(), entry("foo", "bar"), + entry("baz", "")); + } + + @Test + public void parameterMap_customSeparator() { + Navigator navigator = createNavigatorWithState("fooview/foo=bar&baz"); + assertMap(navigator.getStateParameterMap("a"), entry("foo", "b"), + entry("r&b", ""), entry("z", "")); + } + + @SafeVarargs + private final void assertMap(Map<String, String> map, + Entry<String, String>... entries) { + Assert.assertEquals(entries.length, map.size()); + for (Entry<String, String> entry : entries) { + Assert.assertTrue( + "Map should contain a key called '" + entry.getKey() + "'", + map.containsKey(entry.getKey())); + Assert.assertEquals(entry.getValue(), map.get(entry.getKey())); + } + + } + + private Entry<String, String> entry(String key, String value) { + return new Entry<String, String>() { + + @Override + public String getKey() { + return key; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String setValue(String value) { + throw new UnsupportedOperationException(); + } + + }; + } + + private Navigator createNavigatorWithState(String state) { + TestNavigationStateManager manager = new TestNavigationStateManager(); + Navigator navigator = new Navigator(createMockUI(), manager, + EasyMock.createMock(ViewDisplay.class)); + manager.setState(state); + return navigator; + } } |