浏览代码

Add getStateParameterMap to Navigator to get parameters as a map (#9517)

tags/8.1.0.beta2
Peter Lehto 7 年前
父节点
当前提交
cb1a2b9947

+ 79
- 8
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;

@@ -741,6 +744,76 @@ public class Navigator implements Serializable {
return getStateManager().getState();
}

/**
* 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.
*
@@ -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;

+ 109
- 18
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;
}
}

正在加载...
取消
保存