Skip to content

Commit 8d016af

Browse files
committed
Merge pull request #65 from domaframework/lenient-snakecase
スネークケース区切りについて前バージョンとの互換機能を追加しました
2 parents e4bd334 + af536b4 commit 8d016af

File tree

3 files changed

+110
-3
lines changed

3 files changed

+110
-3
lines changed

src/main/java/org/seasar/doma/internal/util/StringUtil.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.seasar.doma.internal.util;
1717

1818
import java.nio.CharBuffer;
19+
import java.util.function.Function;
1920

2021
/**
2122
* {@link String} のユーティリティクラスです。
@@ -85,17 +86,45 @@ public static String fromSnakeCaseToCamelCase(String text) {
8586
}
8687

8788
/**
88-
* キャメルケースをアンダースコア区切りの大文字に変換します。
89+
* キャメルケースをアンダースコア区切りに変換します。
90+
* <p>
91+
* 数字の直後に大文字が続く場合、アンダースコア区切りの対象となります。
8992
*
9093
* @param text
9194
* 文字列
9295
* @return 変換された文字列。 ただし、{@code text} が {@code null} の場合は {@code null}、
9396
* {@code text} が空文字の場合は空文字を返します。
9497
*/
9598
public static String fromCamelCaseToSnakeCase(String text) {
99+
return fromCamelCaseToSnakeCaseInternal(text, false);
100+
}
101+
102+
/**
103+
* キャメルケースをアンダースコア区切りに変換します。
104+
* <p>
105+
* 数字の直後に大文字が続く場合、アンダースコア区切りの対象となりません。
106+
*
107+
* @param text
108+
* 文字列
109+
* @return 変換された文字列。 ただし、{@code text} が {@code null} の場合は {@code null}、
110+
* {@code text} が空文字の場合は空文字を返します。
111+
*/
112+
public static String fromCamelCaseToSnakeCaseWithLenient(String text) {
113+
return fromCamelCaseToSnakeCaseInternal(text, true);
114+
}
115+
116+
private static String fromCamelCaseToSnakeCaseInternal(String text,
117+
boolean lenient) {
96118
if (isNullOrEmpty(text)) {
97119
return text;
98120
}
121+
Function<Character, Boolean> isNotUpperCase;
122+
if (lenient) {
123+
isNotUpperCase = Character::isLowerCase;
124+
} else {
125+
isNotUpperCase = c -> Character.isLowerCase(c)
126+
|| Character.isDigit(c);
127+
}
99128
StringBuilder result = new StringBuilder();
100129
CharBuffer buf = CharBuffer.wrap(text);
101130
while (buf.hasRemaining()) {
@@ -104,7 +133,7 @@ public static String fromCamelCaseToSnakeCase(String text) {
104133
buf.mark();
105134
if (buf.hasRemaining()) {
106135
char c2 = buf.get();
107-
if ((Character.isLowerCase(c) || Character.isDigit(c)) && Character.isUpperCase(c2)) {
136+
if (isNotUpperCase.apply(c) && Character.isUpperCase(c2)) {
108137
result.append("_");
109138
}
110139
buf.reset();

src/main/java/org/seasar/doma/jdbc/entity/NamingType.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public String revert(String text) {
6262
* スネークケースの大文字に変換します。
6363
* <p>
6464
* たとえば、<code>aaaBbb</code> を <code>AAA_BBB</code> に変換します。
65+
* <p>
66+
* 2.2.0 から、入力値において数字の直後に大文字が続く箇所はアンダースコアの挿入対象になりました。
67+
*
68+
* たとえば、<code>aaa3Bbb</code> を <code>AAA3_BBB</code> に変換します。
6569
*/
6670
SNAKE_UPPER_CASE {
6771

@@ -88,6 +92,10 @@ public String revert(String text) {
8892
* スネークケースの小文字に変換します。
8993
* <p>
9094
* たとえば、<code>aaaBbb</code> を <code>aaa_bbb</code> に変換します。
95+
* <p>
96+
* 2.2.0 から、入力値において数字の直後に大文字が続く箇所はアンダースコアの挿入対象になりました。
97+
*
98+
* たとえば、<code>aaa3Bbb</code> を <code>aaa3_bbb</code> に変換します。
9199
*/
92100
SNAKE_LOWER_CASE {
93101

@@ -110,6 +118,66 @@ public String revert(String text) {
110118

111119
},
112120

121+
/**
122+
* スネークケースの大文字に変換します。ただし、アンダースコアを挿入する判断が厳格ではありません。具体的には、
123+
* 入力値において数字の直後に大文字が続く箇所にアンダースコアを挿入しません。
124+
* <p>
125+
* この定義は、2.1.0 以前の {@link NamingType#SNAKE_UPPER_CASE} と同じ挙動をし、
126+
* 過去との互換性のためだけに存在します。
127+
*
128+
* @since 2.2.0
129+
*/
130+
LENIENT_SNAKE_UPPER_CASE {
131+
132+
@Override
133+
public String apply(String text) {
134+
if (text == null) {
135+
throw new DomaNullPointerException("text");
136+
}
137+
String s = StringUtil.fromCamelCaseToSnakeCaseWithLenient(text);
138+
return s.toUpperCase();
139+
}
140+
141+
@Override
142+
public String revert(String text) {
143+
if (text == null) {
144+
throw new DomaNullPointerException("text");
145+
}
146+
return StringUtil.fromSnakeCaseToCamelCase(text);
147+
}
148+
149+
},
150+
151+
/**
152+
* スネークケースの小文字に変換します。ただし、アンダースコアを挿入する判断が厳格ではありません。具体的には、
153+
* 入力値において数字の直後に大文字が続く箇所にアンダースコアを挿入しません。
154+
* <p>
155+
* この定義は、2.1.0 以前の {@link NamingType#SNAKE_LOWER_CASE} と同じ挙動をし、
156+
* 過去との互換性のためだけに存在します。
157+
*
158+
* @since 2.2.0
159+
*/
160+
LENIENT_SNAKE_LOWER_CASE {
161+
162+
@Override
163+
public String apply(String text) {
164+
if (text == null) {
165+
throw new DomaNullPointerException("text");
166+
}
167+
String s = StringUtil.fromCamelCaseToSnakeCaseWithLenient(text);
168+
return s.toLowerCase();
169+
}
170+
171+
@Override
172+
public String revert(String text) {
173+
if (text == null) {
174+
throw new DomaNullPointerException("text");
175+
}
176+
return StringUtil.fromSnakeCaseToCamelCase(text);
177+
}
178+
179+
},
180+
113181
/**
114182
* 大文字に変換します。
115183
* <p>

src/test/java/org/seasar/doma/internal/util/StringUtilTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,17 @@ public void testFromCamelCaseToSnakeCase() throws Exception {
4444
assertEquals("aaa_bbb_ccc",
4545
StringUtil.fromCamelCaseToSnakeCase("aaaBbbCcc"));
4646
assertEquals("abc", StringUtil.fromCamelCaseToSnakeCase("abc"));
47-
assertEquals("aa1_bbb_ccc", StringUtil.fromCamelCaseToSnakeCase("aa1BbbCcc"));
47+
assertEquals("aa1_bbb_ccc",
48+
StringUtil.fromCamelCaseToSnakeCase("aa1BbbCcc"));
49+
}
50+
51+
public void testFromCamelCaseToSnakeCaseWithLenient() throws Exception {
52+
assertEquals("aaa_bbb_ccc",
53+
StringUtil.fromCamelCaseToSnakeCaseWithLenient("aaaBbbCcc"));
54+
assertEquals("abc",
55+
StringUtil.fromCamelCaseToSnakeCaseWithLenient("abc"));
56+
assertEquals("aa1bbb_ccc",
57+
StringUtil.fromCamelCaseToSnakeCaseWithLenient("aa1BbbCcc"));
4858
}
4959

5060
public void testIsWhitespace() throws Exception {

0 commit comments

Comments
 (0)