1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 package gov.nist.secauto.metaschema.databind.codegen.impl;
40
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.Locale;
44
45
46
47
48 @SuppressWarnings("PMD")
49 class NameUtil {
50 protected static boolean isPunct(char ch) {
51 return ch == '-' || ch == '.' || ch == ':' || ch == '_' || ch == '·' || ch == '·' || ch == '' || ch == '۞';
52 }
53
54
55
56
57
58
59
60
61
62 public static String capitalize(String str) {
63 if (!Character.isLowerCase(str.charAt(0))) {
64 return str;
65 }
66 StringBuilder sb = new StringBuilder(str.length());
67 sb.append(String.valueOf(str.charAt(0)).toUpperCase(Locale.ENGLISH));
68 sb.append(str.substring(1).toLowerCase(Locale.ENGLISH));
69 return sb.toString();
70 }
71
72
73 @SuppressWarnings({
74 "checkstyle:MissingSwitchDefaultCheck",
75 })
76 private static int nextBreak(String str, int start) {
77 int len = str.length();
78
79 char c1 = str.charAt(start);
80 int t1 = classify(c1);
81
82 for (int i = start + 1; i < len; i++) {
83
84
85 int t0 = t1;
86
87 c1 = str.charAt(i);
88 t1 = classify(c1);
89
90 switch (actionTable[t0 * 5 + t1]) {
91 case ACTION_CHECK_PUNCT:
92 if (isPunct(c1)) {
93 return i;
94 }
95 break;
96 case ACTION_CHECK_C2:
97 if (i < len - 1) {
98 char c2 = str.charAt(i + 1);
99 if (Character.isLowerCase(c2)) {
100 return i;
101 }
102 }
103 break;
104 case ACTION_BREAK:
105 return i;
106 }
107 }
108 return -1;
109 }
110
111
112
113 protected static final int UPPER_LETTER = 0;
114 protected static final int LOWER_LETTER = 1;
115 protected static final int OTHER_LETTER = 2;
116 protected static final int DIGIT = 3;
117 protected static final int OTHER = 4;
118
119
120
121
122 private static final byte[] actionTable = new byte[5 * 5];
123
124
125 private static final byte ACTION_CHECK_PUNCT = 0;
126 private static final byte ACTION_CHECK_C2 = 1;
127 private static final byte ACTION_BREAK = 2;
128 private static final byte ACTION_NOBREAK = 3;
129
130
131
132
133
134 private static byte decideAction(int t0, int t1) {
135 if (t0 == OTHER && t1 == OTHER) {
136 return ACTION_CHECK_PUNCT;
137 }
138 if ((t0 == DIGIT) ^ (t1 == DIGIT)) {
139 return ACTION_BREAK;
140 }
141 if (t0 == LOWER_LETTER && t1 != LOWER_LETTER) {
142 return ACTION_BREAK;
143 }
144 if ((t0 <= OTHER_LETTER) ^ (t1 <= OTHER_LETTER)) {
145 return ACTION_BREAK;
146 }
147 if ((t0 == OTHER_LETTER) ^ (t1 == OTHER_LETTER)) {
148 return ACTION_BREAK;
149 }
150 if (t0 == UPPER_LETTER && t1 == UPPER_LETTER) {
151 return ACTION_CHECK_C2;
152 }
153
154 return ACTION_NOBREAK;
155 }
156
157 static {
158
159 for (int t0 = 0; t0 < 5; t0++) {
160 for (int t1 = 0; t1 < 5; t1++) {
161 actionTable[t0 * 5 + t1] = decideAction(t0, t1);
162 }
163 }
164 }
165
166
167
168
169
170
171
172
173 protected static int classify(char ch) {
174 switch (Character.getType(ch)) {
175 case Character.UPPERCASE_LETTER:
176 return UPPER_LETTER;
177 case Character.LOWERCASE_LETTER:
178 return LOWER_LETTER;
179 case Character.TITLECASE_LETTER:
180 case Character.MODIFIER_LETTER:
181 case Character.OTHER_LETTER:
182 return OTHER_LETTER;
183 case Character.DECIMAL_DIGIT_NUMBER:
184 return DIGIT;
185 default:
186 return OTHER;
187 }
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201 public static List<String> toWordList(String str) {
202 ArrayList<String> retval = new ArrayList<>();
203 int len = str.length();
204 for (int i = 0; i < len;) {
205
206
207 while (i < len) {
208 if (!isPunct(str.charAt(i))) {
209 break;
210 }
211 i++;
212 }
213 if (i >= len) {
214 break;
215 }
216
217
218 int breakPos = nextBreak(str, i);
219 String word = (breakPos == -1) ? str.substring(i) : str.substring(i, breakPos);
220 retval.add(escape(capitalize(word)));
221 if (breakPos == -1) {
222 break;
223 }
224 i = breakPos;
225 }
226
227
228
229
230
231 return retval;
232 }
233
234 protected static String toMixedCaseName(List<String> ss, boolean startUpper) {
235 StringBuilder sb = new StringBuilder();
236 if (!ss.isEmpty()) {
237 sb.append(startUpper ? ss.get(0) : ss.get(0).toLowerCase(Locale.ENGLISH));
238 for (int i = 1; i < ss.size(); i++) {
239 sb.append(ss.get(i));
240 }
241 }
242 return sb.toString();
243 }
244
245 protected static String toMixedCaseVariableName(String[] ss,
246 boolean startUpper,
247 boolean cdrUpper) {
248 if (cdrUpper) {
249 for (int i = 1; i < ss.length; i++) {
250 ss[i] = capitalize(ss[i]);
251 }
252 }
253 StringBuilder sb = new StringBuilder();
254 if (ss.length > 0) {
255 sb.append(startUpper ? ss[0] : ss[0].toLowerCase(Locale.ENGLISH));
256 for (int i = 1; i < ss.length; i++) {
257 sb.append(ss[i]);
258 }
259 }
260 return sb.toString();
261 }
262
263
264
265
266
267
268
269
270
271 public String toConstantName(String str) {
272 return toConstantName(toWordList(str));
273 }
274
275
276
277
278
279
280
281
282
283 public String toConstantName(List<String> ss) {
284 StringBuilder sb = new StringBuilder();
285 if (!ss.isEmpty()) {
286 sb.append(ss.get(0).toUpperCase(Locale.ENGLISH));
287 for (int i = 1; i < ss.size(); i++) {
288 sb.append('_');
289 sb.append(ss.get(i).toUpperCase(Locale.ENGLISH));
290 }
291 }
292 return sb.toString();
293 }
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 @SuppressWarnings({
310 "checkstyle:MissingSwitchDefaultCheck",
311 "checkstyle:AvoidEscapedUnicodeCharactersCheck"
312 })
313 public static void escape(StringBuilder sb, String str, int start) {
314 int len = str.length();
315 for (int i = start; i < len; i++) {
316 char ch = str.charAt(i);
317 if (Character.isJavaIdentifierPart(ch)) {
318 sb.append(ch);
319 } else {
320 sb.append('_');
321 if (ch <= '\u000f') {
322 sb.append("000");
323 } else if (ch <= '\u00ff') {
324 sb.append("00");
325 } else if (ch <= '\u0fff') {
326 sb.append('0');
327 }
328 sb.append(Integer.toString(ch, 16));
329 }
330 }
331 }
332
333
334
335
336
337 private static String escape(String str) {
338 int len = str.length();
339 for (int i = 0; i < len; i++) {
340 if (!Character.isJavaIdentifierPart(str.charAt(i))) {
341 StringBuilder sb = new StringBuilder(str.substring(0, i));
342 escape(sb, str, i);
343 return sb.toString();
344 }
345 }
346 return str;
347 }
348 }