View Javadoc
1   /*
2    *    Copyright 2006-2026 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.mybatis.generator.internal.util;
17  
18  import java.util.Collections;
19  import java.util.HashSet;
20  import java.util.Set;
21  import java.util.StringTokenizer;
22  import java.util.function.Consumer;
23  import java.util.function.Function;
24  import java.util.function.Supplier;
25  import java.util.function.UnaryOperator;
26  
27  import org.jspecify.annotations.Nullable;
28  
29  public class StringUtility {
30  
31      /**
32       * Utility class. No instances allowed
33       */
34      private StringUtility() {
35          super();
36      }
37  
38      public static @Nullable String trimToNull(@Nullable String s) {
39          if (s == null) {
40              return null;
41          } else {
42              var d = s.trim();
43              return d.isEmpty() ? null : d;
44          }
45      }
46  
47      public static @Nullable Boolean parseNullableBoolean(@Nullable String s) {
48          return s == null ? null : Boolean.valueOf(s);
49      }
50  
51      public static boolean stringHasValue(@Nullable String s) {
52          return s != null && !s.isEmpty();
53      }
54  
55      public static String stringValueOrElse(@Nullable String s, String defaultValue) {
56          if (stringHasValue(s)) {
57              return s;
58          } else {
59              return defaultValue;
60          }
61      }
62  
63      public static <T extends Throwable> String stringValueOrElseThrow(@Nullable String s,
64                                                                        Supplier<T> exceptionSupplier) throws T {
65          if (stringHasValue(s)) {
66              return s;
67          } else {
68              throw exceptionSupplier.get();
69          }
70      }
71  
72      public static String stringValueOrElseGet(@Nullable String s, Supplier<String> supplier) {
73          return mapStringValueOrElseGet(s, UnaryOperator.identity(), supplier);
74      }
75  
76      public static <T> T mapStringValueOrElseGet(@Nullable String s, Function<String, T> mapper,
77                                                  Supplier<T> supplier) {
78          if (stringHasValue(s)) {
79              return mapper.apply(s);
80          } else {
81              return supplier.get();
82          }
83      }
84  
85      public static String mapStringValueOrElse(@Nullable String s, UnaryOperator<String> mapper, String defaultValue) {
86          if (stringHasValue(s)) {
87              return mapper.apply(s);
88          } else {
89              return defaultValue;
90          }
91      }
92  
93      public static void ifStringHasValueElse(@Nullable String s, Consumer<String> consumer,
94                                              Runnable runnable) {
95          if (stringHasValue(s)) {
96              consumer.accept(s);
97          } else {
98              runnable.run();
99          }
100     }
101 
102     public static String composeFullyQualifiedTableName(@Nullable String catalog,
103             @Nullable String schema, String tableName, char separator) {
104         StringBuilder sb = new StringBuilder();
105 
106         if (stringHasValue(catalog)) {
107             sb.append(catalog);
108             sb.append(separator);
109         }
110 
111         if (stringHasValue(schema)) {
112             sb.append(schema);
113             sb.append(separator);
114         } else {
115             if (!sb.isEmpty()) {
116                 sb.append(separator);
117             }
118         }
119 
120         sb.append(tableName);
121 
122         return sb.toString();
123     }
124 
125     public static boolean stringContainsSpace(@Nullable String s) {
126         return s != null && s.indexOf(' ') != -1;
127     }
128 
129     public static String escapeStringForJava(String s) {
130         StringTokenizer st = new StringTokenizer(s, "\"", true); //$NON-NLS-1$
131         StringBuilder sb = new StringBuilder();
132         while (st.hasMoreTokens()) {
133             String token = st.nextToken();
134             if ("\"".equals(token)) { //$NON-NLS-1$
135                 sb.append("\\\""); //$NON-NLS-1$
136             } else {
137                 sb.append(token);
138             }
139         }
140 
141         return sb.toString();
142     }
143 
144     public static String escapeStringForKotlin(String s) {
145         StringTokenizer st = new StringTokenizer(s, "\"$", true); //$NON-NLS-1$
146         StringBuilder sb = new StringBuilder();
147         while (st.hasMoreTokens()) {
148             String token = st.nextToken();
149             if ("\"".equals(token)) { //$NON-NLS-1$
150                 sb.append("\\\""); //$NON-NLS-1$
151             } else if ("$".equals(token)) { //$NON-NLS-1$
152                 sb.append("\\$"); //$NON-NLS-1$
153             } else {
154                 sb.append(token);
155             }
156         }
157 
158         return sb.toString();
159     }
160 
161     public static boolean isTrue(@Nullable String s) {
162         return Boolean.parseBoolean(s);
163     }
164 
165     public static boolean stringContainsSQLWildcard(@Nullable String s) {
166         if (s == null) {
167             return false;
168         }
169 
170         return s.indexOf('%') != -1 || s.indexOf('_') != -1;
171     }
172 
173     /**
174      * Given an input string, tokenize on the commas and trim all tokens. Returns an empty set if the input string is
175      * null.
176      *
177      * @param in string to tokenize.
178      *
179      * @return Set of tokens
180      */
181     public static Set<String> tokenize(@Nullable String in) {
182         return mapStringValueOrElseGet(in, str -> {
183             Set<String> answer = new HashSet<>();
184             StringTokenizer st = new StringTokenizer(str, ","); //$NON-NLS-1$
185             while (st.hasMoreTokens()) {
186                 String s = st.nextToken().trim();
187                 if (!s.isEmpty()) {
188                     answer.add(s);
189                 }
190             }
191             return answer;
192         }, Collections::emptySet);
193     }
194 
195     public static String convertCamelCaseToSnakeCase(String in) {
196         if (in.chars().anyMatch(Character::isLowerCase)) {
197             return in
198                     .replaceAll("([A-Z])(?=[A-Z])", "$1_") //$NON-NLS-1$ //$NON-NLS-2$
199                     .replaceAll("([a-z])([A-Z])", "$1_$2") //$NON-NLS-1$ //$NON-NLS-2$
200                     .toUpperCase();
201         } else {
202             // if all upper case, then return the string as is
203             return in;
204         }
205     }
206 }