summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/src/com/vaadin/ui/DefaultFieldFactory.java38
-rw-r--r--server/src/com/vaadin/ui/Grid.java4
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java8
-rw-r--r--shared/src/com/vaadin/shared/util/SharedUtil.java136
-rw-r--r--shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java66
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java6
6 files changed, 200 insertions, 58 deletions
diff --git a/server/src/com/vaadin/ui/DefaultFieldFactory.java b/server/src/com/vaadin/ui/DefaultFieldFactory.java
index ad6461686c..535943bcd5 100644
--- a/server/src/com/vaadin/ui/DefaultFieldFactory.java
+++ b/server/src/com/vaadin/ui/DefaultFieldFactory.java
@@ -20,6 +20,7 @@ import java.util.Date;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
+import com.vaadin.shared.util.SharedUtil;
/**
* This class contains a basic implementation for both {@link FormFieldFactory}
@@ -75,42 +76,7 @@ public class DefaultFieldFactory implements FormFieldFactory, TableFieldFactory
* @return the formatted caption string
*/
public static String createCaptionByPropertyId(Object propertyId) {
- String name = propertyId.toString();
- if (name.length() > 0) {
-
- int dotLocation = name.lastIndexOf('.');
- if (dotLocation > 0 && dotLocation < name.length() - 1) {
- name = name.substring(dotLocation + 1);
- }
- if (name.indexOf(' ') < 0
- && name.charAt(0) == Character.toLowerCase(name.charAt(0))
- && name.charAt(0) != Character.toUpperCase(name.charAt(0))) {
- StringBuffer out = new StringBuffer();
- out.append(Character.toUpperCase(name.charAt(0)));
- int i = 1;
-
- while (i < name.length()) {
- int j = i;
- for (; j < name.length(); j++) {
- char c = name.charAt(j);
- if (Character.toLowerCase(c) != c
- && Character.toUpperCase(c) == c) {
- break;
- }
- }
- if (j == name.length()) {
- out.append(name.substring(i));
- } else {
- out.append(name.substring(i, j));
- out.append(" " + name.charAt(j));
- }
- i = j + 1;
- }
-
- name = out.toString();
- }
- }
- return name;
+ return SharedUtil.propertyIdToHumanFriendly(propertyId);
}
/**
diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java
index b9f0ec86aa..b8330e5efc 100644
--- a/server/src/com/vaadin/ui/Grid.java
+++ b/server/src/com/vaadin/ui/Grid.java
@@ -76,6 +76,7 @@ import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.ScrollDestination;
import com.vaadin.shared.ui.grid.SortDirection;
import com.vaadin.shared.ui.grid.SortEventOriginator;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.components.grid.Renderer;
import com.vaadin.ui.components.grid.SortOrderChangeEvent;
import com.vaadin.ui.components.grid.SortOrderChangeListener;
@@ -2119,7 +2120,8 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
header.addColumn(datasourcePropertyId);
footer.addColumn(datasourcePropertyId);
- column.setHeaderCaption(String.valueOf(datasourcePropertyId));
+ column.setHeaderCaption(SharedUtil.camelCaseToHumanFriendly(String
+ .valueOf(datasourcePropertyId)));
return column;
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
index e9b33ba879..366176c3fa 100644
--- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
@@ -34,6 +34,7 @@ import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.KeyMapper;
import com.vaadin.shared.ui.grid.GridColumnState;
import com.vaadin.shared.ui.grid.GridState;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column;
@@ -79,9 +80,10 @@ public class GridColumns {
Column column = grid.getColumn(propertyId);
assertNotNull(column);
- // Property id should be the column header by default
- assertEquals(propertyId.toString(), grid.getDefaultHeaderRow()
- .getCell(propertyId).getText());
+ // Humanized property id should be the column header by default
+ assertEquals(
+ SharedUtil.camelCaseToHumanFriendly(propertyId.toString()),
+ grid.getDefaultHeaderRow().getCell(propertyId).getText());
}
}
diff --git a/shared/src/com/vaadin/shared/util/SharedUtil.java b/shared/src/com/vaadin/shared/util/SharedUtil.java
index 7276f418fa..b40d8f03bb 100644
--- a/shared/src/com/vaadin/shared/util/SharedUtil.java
+++ b/shared/src/com/vaadin/shared/util/SharedUtil.java
@@ -60,4 +60,140 @@ public class SharedUtil implements Serializable {
*/
public static final String SIZE_PATTERN = "^(-?\\d*(?:\\.\\d+)?)(%|px|em|rem|ex|in|cm|mm|pt|pc)?$";
+ /**
+ * Splits a camelCaseString into an array of words with the casing
+ * preserved.
+ *
+ * @since 7.4
+ * @param camelCaseString
+ * The input string in camelCase format
+ * @return An array with one entry per word in the input string
+ */
+ public static String[] splitCamelCase(String camelCaseString) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < camelCaseString.length(); i++) {
+ char c = camelCaseString.charAt(i);
+ if (Character.isUpperCase(c) && isWordComplete(camelCaseString, i)) {
+ sb.append(' ');
+ }
+ sb.append(c);
+ }
+ return sb.toString().split(" ");
+ }
+
+ private static boolean isWordComplete(String camelCaseString, int i) {
+ if (i == 0) {
+ // Word can't end at the beginning
+ return false;
+ } else if (!Character.isUpperCase(camelCaseString.charAt(i - 1))) {
+ // Word ends if previous char wasn't upper case
+ return true;
+ } else if (i + 1 < camelCaseString.length()
+ && !Character.isUpperCase(camelCaseString.charAt(i + 1))) {
+ // Word ends if next char isn't upper case
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Converts a camelCaseString to a human friendly format (Camel case
+ * string).
+ * <p>
+ * In general splits words when the casing changes but also handles special
+ * cases such as consecutive upper case characters. Examples:
+ * <p>
+ * {@literal MyBeanContainer} becomes {@literal My Bean Container}
+ * {@literal AwesomeURLFactory} becomes {@literal Awesome URL Factory}
+ * {@literal SomeUriAction} becomes {@literal Some Uri Action}
+ *
+ * @since 7.4
+ * @param camelCaseString
+ * The input string in camelCase format
+ * @return A human friendly version of the input
+ */
+ public static String camelCaseToHumanFriendly(String camelCaseString) {
+ String[] parts = splitCamelCase(camelCaseString);
+ for (int i = 0; i < parts.length; i++) {
+ parts[i] = capitalize(parts[i]);
+ }
+ return join(parts, " ");
+ }
+
+ private static boolean isAllUpperCase(String string) {
+ for (int i = 0; i < string.length(); i++) {
+ char c = string.charAt(i);
+ if (!Character.isUpperCase(c) && !Character.isDigit(c)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Joins the words in the input array together into a single string by
+ * inserting the separator string between each word.
+ *
+ * @since 7.4
+ * @param parts
+ * The array of words
+ * @param separator
+ * The separator string to use between words
+ * @return The constructed string of words and separators
+ */
+ public static String join(String[] parts, String separator) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < parts.length; i++) {
+ sb.append(parts[i]);
+ sb.append(separator);
+ }
+ return sb.substring(0, sb.length() - 1);
+ }
+
+ /**
+ * Capitalizes the first character in the given string
+ *
+ * @since 7.4
+ * @param string
+ * The string to capitalize
+ * @return The capitalized string
+ */
+ public static String capitalize(String string) {
+ if (string == null) {
+ return null;
+ }
+
+ if (string.length() <= 1) {
+ return string.toUpperCase();
+ }
+
+ return string.substring(0, 1).toUpperCase() + string.substring(1);
+ }
+
+ /**
+ * Converts a property id to a human friendly format. Handles nested
+ * properties by only considering the last part, e.g. "address.streetName"
+ * is equal to "streetName" for this method.
+ *
+ * @since 7.4
+ * @param propertyId
+ * The propertyId to format
+ * @return A human friendly version of the property id
+ */
+ public static String propertyIdToHumanFriendly(Object propertyId) {
+ String string = propertyId.toString();
+ if (string.isEmpty()) {
+ return "";
+ }
+
+ // For nested properties, only use the last part
+ int dotLocation = string.lastIndexOf('.');
+ if (dotLocation > 0 && dotLocation < string.length() - 1) {
+ string = string.substring(dotLocation + 1);
+ }
+
+ return camelCaseToHumanFriendly(string);
+ }
+
}
diff --git a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
index b593032bd6..208d4ca7c7 100644
--- a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
+++ b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java
@@ -1,43 +1,79 @@
package com.vaadin.shared.util;
-import org.junit.Before;
-import org.junit.Test;
-
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
-public class SharedUtilTests {
-
- private SharedUtil sut;
+import org.junit.Assert;
+import org.junit.Test;
- @Before
- public void setup() {
- sut = new SharedUtil();
- }
+public class SharedUtilTests {
@Test
public void trailingSlashIsTrimmed() {
- assertThat(sut.trimTrailingSlashes("/path/"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path/"), is("/path"));
}
@Test
public void noTrailingSlashForTrimming() {
- assertThat(sut.trimTrailingSlashes("/path"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path"), is("/path"));
}
@Test
public void trailingSlashesAreTrimmed() {
- assertThat(sut.trimTrailingSlashes("/path///"), is("/path"));
+ assertThat(SharedUtil.trimTrailingSlashes("/path///"), is("/path"));
}
@Test
public void emptyStringIsHandled() {
- assertThat(sut.trimTrailingSlashes(""), is(""));
+ assertThat(SharedUtil.trimTrailingSlashes(""), is(""));
}
@Test
public void rootSlashIsTrimmed() {
- assertThat(sut.trimTrailingSlashes("/"), is(""));
+ assertThat(SharedUtil.trimTrailingSlashes("/"), is(""));
}
+ @Test
+ public void camelCaseToHumanReadable() {
+ Assert.assertEquals("First Name",
+ SharedUtil.camelCaseToHumanFriendly("firstName"));
+ Assert.assertEquals("First Name",
+ SharedUtil.camelCaseToHumanFriendly("first name"));
+ Assert.assertEquals("First Name2",
+ SharedUtil.camelCaseToHumanFriendly("firstName2"));
+ Assert.assertEquals("First",
+ SharedUtil.camelCaseToHumanFriendly("first"));
+ Assert.assertEquals("First",
+ SharedUtil.camelCaseToHumanFriendly("First"));
+ Assert.assertEquals("Some XYZ Abbreviation",
+ SharedUtil.camelCaseToHumanFriendly("SomeXYZAbbreviation"));
+
+ // Javadoc examples
+ Assert.assertEquals("My Bean Container",
+ SharedUtil.camelCaseToHumanFriendly("MyBeanContainer"));
+ Assert.assertEquals("Awesome URL Factory",
+ SharedUtil.camelCaseToHumanFriendly("AwesomeURLFactory"));
+ Assert.assertEquals("Some Uri Action",
+ SharedUtil.camelCaseToHumanFriendly("SomeUriAction"));
+
+ }
+
+ @Test
+ public void splitCamelCase() {
+ assertCamelCaseSplit("firstName", "first", "Name");
+ assertCamelCaseSplit("fooBar", "foo", "Bar");
+ assertCamelCaseSplit("fooBar", "foo", "Bar");
+ assertCamelCaseSplit("fBar", "f", "Bar");
+ assertCamelCaseSplit("FBar", "F", "Bar");
+ assertCamelCaseSplit("MYCdi", "MY", "Cdi");
+ assertCamelCaseSplit("MyCDIUI", "My", "CDIUI");
+ assertCamelCaseSplit("MyCDIUITwo", "My", "CDIUI", "Two");
+ assertCamelCaseSplit("first name", "first", "name");
+
+ }
+
+ private void assertCamelCaseSplit(String camelCaseString, String... parts) {
+ String[] splitParts = SharedUtil.splitCamelCase(camelCaseString);
+ Assert.assertArrayEquals(parts, splitParts);
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
index cb0113bcca..f763f7820a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
@@ -89,12 +89,12 @@ public class GridColspansTest extends MultiBrowserTest {
GridElement grid = $(GridElement.class).first();
assertEquals("Failed initial condition.", "all the stuff", grid
.getHeaderCell(0, 1).getText().toLowerCase());
- assertEquals("Failed initial condition.", "firstname", grid
+ assertEquals("Failed initial condition.", "first name", grid
.getHeaderCell(2, 1).getText().toLowerCase());
$(ButtonElement.class).first().click();
assertEquals("Header text changed on column hide.", "all the stuff",
grid.getHeaderCell(0, 1).getText().toLowerCase());
- assertEquals("Failed initial condition.", "lastname", grid
+ assertEquals("Failed initial condition.", "last name", grid
.getHeaderCell(2, 1).getText().toLowerCase());
}
@@ -106,7 +106,7 @@ public class GridColspansTest extends MultiBrowserTest {
GridCellElement headerCell = grid.getHeaderCell(1, 1);
assertEquals("Failed initial condition.", "full name", headerCell
.getText().toLowerCase());
- assertEquals("Failed initial condition.", "firstname", grid
+ assertEquals("Failed initial condition.", "first name", grid
.getHeaderCell(2, 1).getText().toLowerCase());
$(ButtonElement.class).get(1).click();
headerCell = grid.getHeaderCell(1, 1);