001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.lang3;
018
019 /**
020 * <p>Operations on <code>CharSet</code>s.</p>
021 *
022 * <p>This class handles <code>null</code> input gracefully.
023 * An exception will not be thrown for a <code>null</code> input.
024 * Each method documents its behaviour in more detail.</p>
025 *
026 * <p>#ThreadSafe#</p>
027 * @see CharSet
028 * @author Apache Software Foundation
029 * @author Phil Steitz
030 * @author Gary Gregory
031 * @since 1.0
032 * @version $Id: CharSetUtils.java 918868 2010-03-04 06:22:16Z bayard $
033 */
034 public class CharSetUtils {
035
036 /**
037 * <p>CharSetUtils instances should NOT be constructed in standard programming.
038 * Instead, the class should be used as <code>CharSetUtils.evaluateSet(null);</code>.</p>
039 *
040 * <p>This constructor is public to permit tools that require a JavaBean instance
041 * to operate.</p>
042 */
043 public CharSetUtils() {
044 super();
045 }
046
047 // Squeeze
048 //-----------------------------------------------------------------------
049 /**
050 * <p>Squeezes any repetitions of a character that is mentioned in the
051 * supplied set.</p>
052 *
053 * <pre>
054 * CharSetUtils.squeeze(null, *) = null
055 * CharSetUtils.squeeze("", *) = ""
056 * CharSetUtils.squeeze(*, null) = *
057 * CharSetUtils.squeeze(*, "") = *
058 * CharSetUtils.squeeze("hello", "k-p") = "helo"
059 * CharSetUtils.squeeze("hello", "a-e") = "hello"
060 * </pre>
061 *
062 * @see CharSet#getInstance(java.lang.String) for set-syntax.
063 * @param str the string to squeeze, may be null
064 * @param set the character set to use for manipulation, may be null
065 * @return modified String, <code>null</code> if null string input
066 */
067 public static String squeeze(String str, String set) {
068 if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
069 return str;
070 }
071 String[] strs = new String[1];
072 strs[0] = set;
073 return squeeze(str, strs);
074 }
075
076 /**
077 * <p>Squeezes any repetitions of a character that is mentioned in the
078 * supplied set.</p>
079 *
080 * <p>An example is:</p>
081 * <ul>
082 * <li>squeeze("hello", {"el"}) => "helo"</li>
083 * </ul>
084 *
085 * @see CharSet#getInstance(java.lang.String) for set-syntax.
086 * @param str the string to squeeze, may be null
087 * @param set the character set to use for manipulation, may be null
088 * @return modified String, <code>null</code> if null string input
089 */
090 public static String squeeze(String str, String[] set) {
091 if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
092 return str;
093 }
094 CharSet chars = CharSet.getInstance(set);
095 StringBuilder buffer = new StringBuilder(str.length());
096 char[] chrs = str.toCharArray();
097 int sz = chrs.length;
098 char lastChar = ' ';
099 char ch = ' ';
100 for (int i = 0; i < sz; i++) {
101 ch = chrs[i];
102 if (chars.contains(ch)) {
103 if ((ch == lastChar) && (i != 0)) {
104 continue;
105 }
106 }
107 buffer.append(ch);
108 lastChar = ch;
109 }
110 return buffer.toString();
111 }
112
113 // Count
114 //-----------------------------------------------------------------------
115 /**
116 * <p>Takes an argument in set-syntax, see evaluateSet,
117 * and returns the number of characters present in the specified string.</p>
118 *
119 * <pre>
120 * CharSetUtils.count(null, *) = 0
121 * CharSetUtils.count("", *) = 0
122 * CharSetUtils.count(*, null) = 0
123 * CharSetUtils.count(*, "") = 0
124 * CharSetUtils.count("hello", "k-p") = 3
125 * CharSetUtils.count("hello", "a-e") = 1
126 * </pre>
127 *
128 * @see CharSet#getInstance(java.lang.String) for set-syntax.
129 * @param str String to count characters in, may be null
130 * @param set String set of characters to count, may be null
131 * @return character count, zero if null string input
132 */
133 public static int count(String str, String set) {
134 if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
135 return 0;
136 }
137 String[] strs = new String[1];
138 strs[0] = set;
139 return count(str, strs);
140 }
141
142 /**
143 * <p>Takes an argument in set-syntax, see evaluateSet,
144 * and returns the number of characters present in the specified string.</p>
145 *
146 * <p>An example would be:</p>
147 * <ul>
148 * <li>count("hello", {"c-f", "o"}) returns 2.</li>
149 * </ul>
150 *
151 * @see CharSet#getInstance(java.lang.String) for set-syntax.
152 * @param str String to count characters in, may be null
153 * @param set String[] set of characters to count, may be null
154 * @return character count, zero if null string input
155 */
156 public static int count(String str, String[] set) {
157 if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
158 return 0;
159 }
160 CharSet chars = CharSet.getInstance(set);
161 int count = 0;
162 char[] chrs = str.toCharArray();
163 int sz = chrs.length;
164 for(int i=0; i<sz; i++) {
165 if(chars.contains(chrs[i])) {
166 count++;
167 }
168 }
169 return count;
170 }
171
172 // Keep
173 //-----------------------------------------------------------------------
174 /**
175 * <p>Takes an argument in set-syntax, see evaluateSet,
176 * and keeps any of characters present in the specified string.</p>
177 *
178 * <pre>
179 * CharSetUtils.keep(null, *) = null
180 * CharSetUtils.keep("", *) = ""
181 * CharSetUtils.keep(*, null) = ""
182 * CharSetUtils.keep(*, "") = ""
183 * CharSetUtils.keep("hello", "hl") = "hll"
184 * CharSetUtils.keep("hello", "le") = "ell"
185 * </pre>
186 *
187 * @see CharSet#getInstance(java.lang.String) for set-syntax.
188 * @param str String to keep characters from, may be null
189 * @param set String set of characters to keep, may be null
190 * @return modified String, <code>null</code> if null string input
191 * @since 2.0
192 */
193 public static String keep(String str, String set) {
194 if (str == null) {
195 return null;
196 }
197 if (str.length() == 0 || StringUtils.isEmpty(set)) {
198 return "";
199 }
200 String[] strs = new String[1];
201 strs[0] = set;
202 return keep(str, strs);
203 }
204
205 /**
206 * <p>Takes an argument in set-syntax, see evaluateSet,
207 * and keeps any of characters present in the specified string.</p>
208 *
209 * <p>An example would be:</p>
210 * <ul>
211 * <li>keep("hello", {"c-f", "o"})
212 * returns "eo"</li>
213 * </ul>
214 *
215 * @see CharSet#getInstance(java.lang.String) for set-syntax.
216 * @param str String to keep characters from, may be null
217 * @param set String[] set of characters to keep, may be null
218 * @return modified String, <code>null</code> if null string input
219 * @since 2.0
220 */
221 public static String keep(String str, String[] set) {
222 if (str == null) {
223 return null;
224 }
225 if (str.length() == 0 || ArrayUtils.isEmpty(set)) {
226 return "";
227 }
228 return modify(str, set, true);
229 }
230
231 // Delete
232 //-----------------------------------------------------------------------
233 /**
234 * <p>Takes an argument in set-syntax, see evaluateSet,
235 * and deletes any of characters present in the specified string.</p>
236 *
237 * <pre>
238 * CharSetUtils.delete(null, *) = null
239 * CharSetUtils.delete("", *) = ""
240 * CharSetUtils.delete(*, null) = *
241 * CharSetUtils.delete(*, "") = *
242 * CharSetUtils.delete("hello", "hl") = "eo"
243 * CharSetUtils.delete("hello", "le") = "ho"
244 * </pre>
245 *
246 * @see CharSet#getInstance(java.lang.String) for set-syntax.
247 * @param str String to delete characters from, may be null
248 * @param set String set of characters to delete, may be null
249 * @return modified String, <code>null</code> if null string input
250 */
251 public static String delete(String str, String set) {
252 if (StringUtils.isEmpty(str) || StringUtils.isEmpty(set)) {
253 return str;
254 }
255 String[] strs = new String[1];
256 strs[0] = set;
257 return delete(str, strs);
258 }
259
260 /**
261 * <p>Takes an argument in set-syntax, see evaluateSet,
262 * and deletes any of characters present in the specified string.</p>
263 *
264 * <p>An example would be:</p>
265 * <ul>
266 * <li>delete("hello", {"c-f", "o"}) returns
267 * "hll"</li>
268 * </ul>
269 *
270 * @see CharSet#getInstance(java.lang.String) for set-syntax.
271 * @param str String to delete characters from, may be null
272 * @param set String[] set of characters to delete, may be null
273 * @return modified String, <code>null</code> if null string input
274 */
275 public static String delete(String str, String[] set) {
276 if (StringUtils.isEmpty(str) || ArrayUtils.isEmpty(set)) {
277 return str;
278 }
279 return modify(str, set, false);
280 }
281
282 //-----------------------------------------------------------------------
283 /**
284 * Implementation of delete and keep
285 *
286 * @param str String to modify characters within
287 * @param set String[] set of characters to modify
288 * @param expect whether to evaluate on match, or non-match
289 * @return modified String
290 */
291 private static String modify(String str, String[] set, boolean expect) {
292 CharSet chars = CharSet.getInstance(set);
293 StringBuilder buffer = new StringBuilder(str.length());
294 char[] chrs = str.toCharArray();
295 int sz = chrs.length;
296 for(int i=0; i<sz; i++) {
297 if(chars.contains(chrs[i]) == expect) {
298 buffer.append(chrs[i]);
299 }
300 }
301 return buffer.toString();
302 }
303
304 }