diff --git a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java index 14e0e3992..0318a33fe 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java @@ -15,11 +15,7 @@ */ package org.springframework.data.repository.config; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.regex.Pattern; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.env.Environment; @@ -27,6 +23,7 @@ import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.config.TypeFilterParser; import org.springframework.data.config.TypeFilterParser.Type; import org.springframework.data.repository.query.QueryLookupStrategy; +import org.springframework.data.util.ParsingUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.w3c.dom.Element; @@ -46,8 +43,6 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou private static final String REPOSITORY_FACTORY_BEAN_CLASS_NAME = "factory-class"; private static final String CONSIDER_NESTED_REPOSITORIES = "consider-nested-repositories"; - private static final Pattern CAMEL_CASE_PARTS = Pattern.compile("(? lowercase = new ArrayList(); - - for (String part : Arrays.asList(CAMEL_CASE_PARTS.split(name))) { - lowercase.add(part.toLowerCase(Locale.US)); - } - - String xmlAttributeName = StringUtils.collectionToDelimitedString(lowercase, "-"); + String xmlAttributeName = ParsingUtils.reconcatenateCamelCase(name, "-"); String attribute = element.getAttribute(xmlAttributeName); return StringUtils.hasText(attribute) ? attribute : null; diff --git a/src/main/java/org/springframework/data/util/ParsingUtils.java b/src/main/java/org/springframework/data/util/ParsingUtils.java new file mode 100644 index 000000000..f227c3677 --- /dev/null +++ b/src/main/java/org/springframework/data/util/ParsingUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Utility methods for {@link String} parsing. + * + * @author Oliver Gierke + * @since 1.5 + */ +public abstract class ParsingUtils { + + private static final String UPPER = "\\p{Lu}|\\P{InBASIC_LATIN}"; + private static final String LOWER = "\\p{Ll}"; + private static final String CAMEL_CASE_REGEX = "(? splitCamelCase(String source) { + return split(source, false); + } + + /** + * Splits up the given camel-case {@link String} and returns the parts in lower case. + * + * @param source must not be {@literal null}. + * @return + */ + public static List splitCamelCaseToLower(String source) { + return split(source, true); + } + + /** + * Reconcatenates the given camel-case source {@link String} using the given delimiter. Will split up the camel-case + * {@link String} and use an uncapitalized version of the parts. + * + * @param source must not be {@literal null}. + * @param delimiter must not be {@literal null}. + * @return + */ + public static String reconcatenateCamelCase(String source, String delimiter) { + + Assert.notNull(source, "Source string must not be null!"); + Assert.notNull(delimiter, "Delimiter must not be null!"); + + return StringUtils.collectionToDelimitedString(splitCamelCaseToLower(source), delimiter); + } + + private static List split(String source, boolean toLower) { + + Assert.notNull(source, "Source string must not be null!"); + + String[] parts = CAMEL_CASE.split(source); + List result = new ArrayList(parts.length); + + for (String part : parts) { + result.add(toLower ? part.toLowerCase() : part); + } + + return Collections.unmodifiableList(result); + } +} diff --git a/src/test/java/org/springframework/data/util/ParsingUtilsUnitTests.java b/src/test/java/org/springframework/data/util/ParsingUtilsUnitTests.java new file mode 100644 index 000000000..1b1a24c75 --- /dev/null +++ b/src/test/java/org/springframework/data/util/ParsingUtilsUnitTests.java @@ -0,0 +1,65 @@ +/* + * Copyright 2014 the original author or authors. + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.util; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Test; + +/** + * Unit tests for {@link ParsingUtils}. + * + * @author Oliver Gierke + */ +public class ParsingUtilsUnitTests { + + /** + * @see DATCMNS-486 + */ + @Test + public void splitsCamelCaseWithAllSortsOfCharacters() { + + String sample = "prefix" + "이름" // + + "Anders" // + + "Øre" // + + "År" // + + "Property1" // + + "생일" // + + "Foo_bar" // + + "FOO_BAR" // + + "Bar$foo" // + + "BAR$FOO" // + + "Suffix"; + + List result = ParsingUtils.splitCamelCaseToLower(sample); + assertThat( + result, + contains("prefix", "이름", "anders", "øre", "år", "property1", "생일", "foo_bar", "foo_bar", "bar$foo", "bar$foo", + "suffix")); + } + + /** + * @see DATCMNS-486 + */ + @Test + public void reconcatenatesCamelCaseString() { + assertThat(ParsingUtils.reconcatenateCamelCase("myCamelCase", "-"), is("my-camel-case")); + } +}