Coverage Report - org.apache.commons.lang3.text.WordUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
WordUtils
100%
122/122
98%
87/88
5
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.lang3.text;
 18  
 
 19  
 import java.util.regex.Pattern;
 20  
 
 21  
 import org.apache.commons.lang3.ArrayUtils;
 22  
 import org.apache.commons.lang3.StringUtils;
 23  
 import org.apache.commons.lang3.SystemUtils;
 24  
 
 25  
 /**
 26  
  * <p>Operations on Strings that contain words.</p>
 27  
  * 
 28  
  * <p>This class tries to handle <code>null</code> input gracefully.
 29  
  * An exception will not be thrown for a <code>null</code> input.
 30  
  * Each method documents its behaviour in more detail.</p>
 31  
  * 
 32  
  * @since 2.0
 33  
  */
 34  
 public class WordUtils {
 35  
 
 36  
     /**
 37  
      * <p><code>WordUtils</code> instances should NOT be constructed in
 38  
      * standard programming. Instead, the class should be used as
 39  
      * <code>WordUtils.wrap("foo bar", 20);</code>.</p>
 40  
      *
 41  
      * <p>This constructor is public to permit tools that require a JavaBean
 42  
      * instance to operate.</p>
 43  
      */
 44  
     public WordUtils() {
 45  2
       super();
 46  2
     }
 47  
 
 48  
     // Wrapping
 49  
     //--------------------------------------------------------------------------
 50  
     /**
 51  
      * <p>Wraps a single line of text, identifying words by <code>' '</code>.</p>
 52  
      * 
 53  
      * <p>New lines will be separated by the system property line separator.
 54  
      * Very long words, such as URLs will <i>not</i> be wrapped.</p>
 55  
      * 
 56  
      * <p>Leading spaces on a new line are stripped.
 57  
      * Trailing spaces are not stripped.</p>
 58  
      *
 59  
      * <table border="1" summary="Wrap Results">
 60  
      *  <tr>
 61  
      *   <th>input</th>
 62  
      *   <th>wrapLength</th>
 63  
      *   <th>result</th>
 64  
      *  </tr>
 65  
      *  <tr>
 66  
      *   <td>null</td>
 67  
      *   <td>*</td>
 68  
      *   <td>null</td>
 69  
      *  </tr>
 70  
      *  <tr>
 71  
      *   <td>""</td>
 72  
      *   <td>*</td>
 73  
      *   <td>""</td>
 74  
      *  </tr>
 75  
      *  <tr>
 76  
      *   <td>"Here is one line of text that is going to be wrapped after 20 columns."</td>
 77  
      *   <td>20</td>
 78  
      *   <td>"Here is one line of\ntext that is going\nto be wrapped after\n20 columns."</td>
 79  
      *  </tr>
 80  
      *  <tr>
 81  
      *   <td>"Click here to jump to the commons website - http://commons.apache.org"</td>
 82  
      *   <td>20</td>
 83  
      *   <td>"Click here to jump\nto the commons\nwebsite -\nhttp://commons.apache.org"</td>
 84  
      *  </tr>
 85  
      *  <tr>
 86  
      *   <td>"Click here, http://commons.apache.org, to jump to the commons website"</td>
 87  
      *   <td>20</td>
 88  
      *   <td>"Click here,\nhttp://commons.apache.org,\nto jump to the\ncommons website"</td>
 89  
      *  </tr>
 90  
      * </table>
 91  
      *
 92  
      * (assuming that '\n' is the systems line separator)
 93  
      *
 94  
      * @param str  the String to be word wrapped, may be null
 95  
      * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
 96  
      * @return a line with newlines inserted, <code>null</code> if null input
 97  
      */
 98  
     public static String wrap(final String str, final int wrapLength) {
 99  16
         return wrap(str, wrapLength, null, false);
 100  
     }
 101  
     
 102  
     /**
 103  
      * <p>Wraps a single line of text, identifying words by <code>' '</code>.</p>
 104  
      * 
 105  
      * <p>Leading spaces on a new line are stripped.
 106  
      * Trailing spaces are not stripped.</p>
 107  
      *
 108  
      * <table border="1" summary="Wrap Results">
 109  
      *  <tr>
 110  
      *   <th>input</th>
 111  
      *   <th>wrapLenght</th>
 112  
      *   <th>newLineString</th>
 113  
      *   <th>wrapLongWords</th>
 114  
      *   <th>result</th>
 115  
      *  </tr>
 116  
      *  <tr>
 117  
      *   <td>null</td>
 118  
      *   <td>*</td>
 119  
      *   <td>*</td>
 120  
      *   <td>true/false</td>
 121  
      *   <td>null</td>
 122  
      *  </tr>
 123  
      *  <tr>
 124  
      *   <td>""</td>
 125  
      *   <td>*</td>
 126  
      *   <td>*</td>
 127  
      *   <td>true/false</td>
 128  
      *   <td>""</td>
 129  
      *  </tr>
 130  
      *  <tr>
 131  
      *   <td>"Here is one line of text that is going to be wrapped after 20 columns."</td>
 132  
      *   <td>20</td>
 133  
      *   <td>"\n"</td>
 134  
      *   <td>true/false</td>
 135  
      *   <td>"Here is one line of\ntext that is going\nto be wrapped after\n20 columns."</td>
 136  
      *  </tr>
 137  
      *  <tr>
 138  
      *   <td>"Here is one line of text that is going to be wrapped after 20 columns."</td>
 139  
      *   <td>20</td>
 140  
      *   <td>"&lt;br /&gt;"</td>
 141  
      *   <td>true/false</td>
 142  
      *   <td>"Here is one line of&lt;br /&gt;text that is going&lt;br /&gt;to be wrapped after&lt;br /&gt;20 columns."</td>
 143  
      *  </tr>
 144  
      *  <tr>
 145  
      *   <td>"Here is one line of text that is going to be wrapped after 20 columns."</td>
 146  
      *   <td>20</td>
 147  
      *   <td>null</td>
 148  
      *   <td>true/false</td>
 149  
      *   <td>"Here is one line of" + systemNewLine + "text that is going" + systemNewLine + "to be wrapped after" + systemNewLine + "20 columns."</td>
 150  
      *  </tr>
 151  
      *  <tr>
 152  
      *   <td>"Click here to jump to the commons website - http://commons.apache.org"</td>
 153  
      *   <td>20</td>
 154  
      *   <td>"\n"</td>
 155  
      *   <td>false</td>
 156  
      *   <td>"Click here to jump\nto the commons\nwebsite -\nhttp://commons.apache.org"</td>
 157  
      *  </tr>
 158  
      *  <tr>
 159  
      *   <td>"Click here to jump to the commons website - http://commons.apache.org"</td>
 160  
      *   <td>20</td>
 161  
      *   <td>"\n"</td>
 162  
      *   <td>true</td>
 163  
      *   <td>"Click here to jump\nto the commons\nwebsite -\nhttp://commons.apach\ne.org"</td>
 164  
      *  </tr>
 165  
      * </table>
 166  
      *
 167  
      * @param str  the String to be word wrapped, may be null
 168  
      * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
 169  
      * @param newLineStr  the string to insert for a new line, 
 170  
      *  <code>null</code> uses the system property line separator
 171  
      * @param wrapLongWords  true if long words (such as URLs) should be wrapped
 172  
      * @return a line with newlines inserted, <code>null</code> if null input
 173  
      */
 174  
     public static String wrap(final String str, int wrapLength, String newLineStr, final boolean wrapLongWords) {
 175  78
         if (str == null) {
 176  16
             return null;
 177  
         }
 178  62
         if (newLineStr == null) {
 179  24
             newLineStr = SystemUtils.LINE_SEPARATOR;
 180  
         }
 181  62
         if (wrapLength < 1) {
 182  8
             wrapLength = 1;
 183  
         }
 184  62
         final int inputLineLength = str.length();
 185  62
         int offset = 0;
 186  62
         final StringBuilder wrappedLine = new StringBuilder(inputLineLength + 32);
 187  
         
 188  280
         while (offset < inputLineLength) {
 189  256
             if (str.charAt(offset) == ' ') {
 190  70
                 offset++;
 191  70
                 continue;
 192  
             }
 193  
             // only last line without leading spaces is left
 194  186
             if(inputLineLength - offset <= wrapLength) {
 195  38
                 break;
 196  
             }
 197  148
             int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
 198  
 
 199  148
             if (spaceToWrapAt >= offset) {
 200  
                 // normal case
 201  122
                 wrappedLine.append(str.substring(offset, spaceToWrapAt));
 202  122
                 wrappedLine.append(newLineStr);
 203  122
                 offset = spaceToWrapAt + 1;
 204  
                 
 205  
             } else {
 206  
                 // really long word or URL
 207  26
                 if (wrapLongWords) {
 208  
                     // wrap really long word one line at a time
 209  4
                     wrappedLine.append(str.substring(offset, wrapLength + offset));
 210  4
                     wrappedLine.append(newLineStr);
 211  4
                     offset += wrapLength;
 212  
                 } else {
 213  
                     // do not wrap really long word, just extend beyond limit
 214  22
                     spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
 215  22
                     if (spaceToWrapAt >= 0) {
 216  14
                         wrappedLine.append(str.substring(offset, spaceToWrapAt));
 217  14
                         wrappedLine.append(newLineStr);
 218  14
                         offset = spaceToWrapAt + 1;
 219  
                     } else {
 220  8
                         wrappedLine.append(str.substring(offset));
 221  8
                         offset = inputLineLength;
 222  
                     }
 223  
                 }
 224  
             }
 225  148
         }
 226  
 
 227  
         // Whatever is left in line is short enough to just pass through
 228  62
         wrappedLine.append(str.substring(offset));
 229  
 
 230  62
         return wrappedLine.toString();
 231  
     }
 232  
 
 233  
     // Capitalizing
 234  
     //-----------------------------------------------------------------------
 235  
     /**
 236  
      * <p>Capitalizes all the whitespace separated words in a String.
 237  
      * Only the first character of each word is changed. To convert the 
 238  
      * rest of each word to lowercase at the same time, 
 239  
      * use {@link #capitalizeFully(String)}.</p>
 240  
      *
 241  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 242  
      * A <code>null</code> input String returns <code>null</code>.
 243  
      * Capitalization uses the Unicode title case, normally equivalent to
 244  
      * upper case.</p>
 245  
      *
 246  
      * <pre>
 247  
      * WordUtils.capitalize(null)        = null
 248  
      * WordUtils.capitalize("")          = ""
 249  
      * WordUtils.capitalize("i am FINE") = "I Am FINE"
 250  
      * </pre>
 251  
      * 
 252  
      * @param str  the String to capitalize, may be null
 253  
      * @return capitalized String, <code>null</code> if null String input
 254  
      * @see #uncapitalize(String)
 255  
      * @see #capitalizeFully(String)
 256  
      */
 257  
     public static String capitalize(final String str) {
 258  18
         return capitalize(str, null);
 259  
     }
 260  
 
 261  
     /**
 262  
      * <p>Capitalizes all the delimiter separated words in a String.
 263  
      * Only the first character of each word is changed. To convert the 
 264  
      * rest of each word to lowercase at the same time, 
 265  
      * use {@link #capitalizeFully(String, char[])}.</p>
 266  
      *
 267  
      * <p>The delimiters represent a set of characters understood to separate words.
 268  
      * The first string character and the first non-delimiter character after a
 269  
      * delimiter will be capitalized. </p>
 270  
      *
 271  
      * <p>A <code>null</code> input String returns <code>null</code>.
 272  
      * Capitalization uses the Unicode title case, normally equivalent to
 273  
      * upper case.</p>
 274  
      *
 275  
      * <pre>
 276  
      * WordUtils.capitalize(null, *)            = null
 277  
      * WordUtils.capitalize("", *)              = ""
 278  
      * WordUtils.capitalize(*, new char[0])     = *
 279  
      * WordUtils.capitalize("i am fine", null)  = "I Am Fine"
 280  
      * WordUtils.capitalize("i aM.fine", {'.'}) = "I aM.Fine"
 281  
      * </pre>
 282  
      * 
 283  
      * @param str  the String to capitalize, may be null
 284  
      * @param delimiters  set of characters to determine capitalization, null means whitespace
 285  
      * @return capitalized String, <code>null</code> if null String input
 286  
      * @see #uncapitalize(String)
 287  
      * @see #capitalizeFully(String)
 288  
      * @since 2.1
 289  
      */
 290  
     public static String capitalize(final String str, final char... delimiters) {
 291  70
         final int delimLen = delimiters == null ? -1 : delimiters.length;
 292  70
         if (StringUtils.isEmpty(str) || delimLen == 0) {
 293  10
             return str;
 294  
         }
 295  60
         final char[] buffer = str.toCharArray();
 296  60
         boolean capitalizeNext = true;
 297  572
         for (int i = 0; i < buffer.length; i++) {
 298  512
             final char ch = buffer[i];
 299  512
             if (isDelimiter(ch, delimiters)) {
 300  112
                 capitalizeNext = true;
 301  400
             } else if (capitalizeNext) {
 302  160
                 buffer[i] = Character.toTitleCase(ch);
 303  160
                 capitalizeNext = false;
 304  
             }
 305  
         }
 306  60
         return new String(buffer);
 307  
     }
 308  
 
 309  
     //-----------------------------------------------------------------------
 310  
     /**
 311  
      * <p>Converts all the whitespace separated words in a String into capitalized words, 
 312  
      * that is each word is made up of a titlecase character and then a series of 
 313  
      * lowercase characters.  </p>
 314  
      *
 315  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 316  
      * A <code>null</code> input String returns <code>null</code>.
 317  
      * Capitalization uses the Unicode title case, normally equivalent to
 318  
      * upper case.</p>
 319  
      *
 320  
      * <pre>
 321  
      * WordUtils.capitalizeFully(null)        = null
 322  
      * WordUtils.capitalizeFully("")          = ""
 323  
      * WordUtils.capitalizeFully("i am FINE") = "I Am Fine"
 324  
      * </pre>
 325  
      * 
 326  
      * @param str  the String to capitalize, may be null
 327  
      * @return capitalized String, <code>null</code> if null String input
 328  
      */
 329  
     public static String capitalizeFully(final String str) {
 330  18
         return capitalizeFully(str, null);
 331  
     }
 332  
 
 333  
     /**
 334  
      * <p>Converts all the delimiter separated words in a String into capitalized words, 
 335  
      * that is each word is made up of a titlecase character and then a series of 
 336  
      * lowercase characters. </p>
 337  
      *
 338  
      * <p>The delimiters represent a set of characters understood to separate words.
 339  
      * The first string character and the first non-delimiter character after a
 340  
      * delimiter will be capitalized. </p>
 341  
      *
 342  
      * <p>A <code>null</code> input String returns <code>null</code>.
 343  
      * Capitalization uses the Unicode title case, normally equivalent to
 344  
      * upper case.</p>
 345  
      *
 346  
      * <pre>
 347  
      * WordUtils.capitalizeFully(null, *)            = null
 348  
      * WordUtils.capitalizeFully("", *)              = ""
 349  
      * WordUtils.capitalizeFully(*, null)            = *
 350  
      * WordUtils.capitalizeFully(*, new char[0])     = *
 351  
      * WordUtils.capitalizeFully("i aM.fine", {'.'}) = "I am.Fine"
 352  
      * </pre>
 353  
      * 
 354  
      * @param str  the String to capitalize, may be null
 355  
      * @param delimiters  set of characters to determine capitalization, null means whitespace
 356  
      * @return capitalized String, <code>null</code> if null String input
 357  
      * @since 2.1
 358  
      */
 359  
     public static String capitalizeFully(String str, final char... delimiters) {
 360  40
         final int delimLen = delimiters == null ? -1 : delimiters.length;
 361  40
         if (StringUtils.isEmpty(str) || delimLen == 0) {
 362  10
             return str;
 363  
         }
 364  30
         str = str.toLowerCase();
 365  30
         return capitalize(str, delimiters);
 366  
     }
 367  
 
 368  
     //-----------------------------------------------------------------------
 369  
     /**
 370  
      * <p>Uncapitalizes all the whitespace separated words in a String.
 371  
      * Only the first character of each word is changed.</p>
 372  
      *
 373  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 374  
      * A <code>null</code> input String returns <code>null</code>.</p>
 375  
      *
 376  
      * <pre>
 377  
      * WordUtils.uncapitalize(null)        = null
 378  
      * WordUtils.uncapitalize("")          = ""
 379  
      * WordUtils.uncapitalize("I Am FINE") = "i am fINE"
 380  
      * </pre>
 381  
      * 
 382  
      * @param str  the String to uncapitalize, may be null
 383  
      * @return uncapitalized String, <code>null</code> if null String input
 384  
      * @see #capitalize(String)
 385  
      */
 386  
     public static String uncapitalize(final String str) {
 387  18
         return uncapitalize(str, null);
 388  
     }
 389  
 
 390  
     /**
 391  
      * <p>Uncapitalizes all the whitespace separated words in a String.
 392  
      * Only the first character of each word is changed.</p>
 393  
      *
 394  
      * <p>The delimiters represent a set of characters understood to separate words.
 395  
      * The first string character and the first non-delimiter character after a
 396  
      * delimiter will be uncapitalized. </p>
 397  
      *
 398  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 399  
      * A <code>null</code> input String returns <code>null</code>.</p>
 400  
      *
 401  
      * <pre>
 402  
      * WordUtils.uncapitalize(null, *)            = null
 403  
      * WordUtils.uncapitalize("", *)              = ""
 404  
      * WordUtils.uncapitalize(*, null)            = *
 405  
      * WordUtils.uncapitalize(*, new char[0])     = *
 406  
      * WordUtils.uncapitalize("I AM.FINE", {'.'}) = "i AM.fINE"
 407  
      * </pre>
 408  
      * 
 409  
      * @param str  the String to uncapitalize, may be null
 410  
      * @param delimiters  set of characters to determine uncapitalization, null means whitespace
 411  
      * @return uncapitalized String, <code>null</code> if null String input
 412  
      * @see #capitalize(String)
 413  
      * @since 2.1
 414  
      */
 415  
     public static String uncapitalize(final String str, final char... delimiters) {
 416  40
         final int delimLen = delimiters == null ? -1 : delimiters.length;
 417  40
         if (StringUtils.isEmpty(str) || delimLen == 0) {
 418  10
             return str;
 419  
         }
 420  30
         final char[] buffer = str.toCharArray();
 421  30
         boolean uncapitalizeNext = true;
 422  286
         for (int i = 0; i < buffer.length; i++) {
 423  256
             final char ch = buffer[i];
 424  256
             if (isDelimiter(ch, delimiters)) {
 425  56
                 uncapitalizeNext = true;
 426  200
             } else if (uncapitalizeNext) {
 427  80
                 buffer[i] = Character.toLowerCase(ch);
 428  80
                 uncapitalizeNext = false;
 429  
             }
 430  
         }
 431  30
         return new String(buffer);
 432  
     }
 433  
 
 434  
     //-----------------------------------------------------------------------
 435  
     /**
 436  
      * <p>Swaps the case of a String using a word based algorithm.</p>
 437  
      * 
 438  
      * <ul>
 439  
      *  <li>Upper case character converts to Lower case</li>
 440  
      *  <li>Title case character converts to Lower case</li>
 441  
      *  <li>Lower case character after Whitespace or at start converts to Title case</li>
 442  
      *  <li>Other Lower case character converts to Upper case</li>
 443  
      * </ul>
 444  
      * 
 445  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 446  
      * A <code>null</code> input String returns <code>null</code>.</p>
 447  
      * 
 448  
      * <pre>
 449  
      * StringUtils.swapCase(null)                 = null
 450  
      * StringUtils.swapCase("")                   = ""
 451  
      * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
 452  
      * </pre>
 453  
      * 
 454  
      * @param str  the String to swap case, may be null
 455  
      * @return the changed String, <code>null</code> if null String input
 456  
      */
 457  
     public static String swapCase(final String str) {
 458  26
         if (StringUtils.isEmpty(str)) {
 459  4
             return str;
 460  
         }
 461  22
         final char[] buffer = str.toCharArray();
 462  
 
 463  22
         boolean whitespace = true;
 464  
 
 465  318
         for (int i = 0; i < buffer.length; i++) {
 466  296
             final char ch = buffer[i];
 467  296
             if (Character.isUpperCase(ch)) {
 468  48
                 buffer[i] = Character.toLowerCase(ch);
 469  48
                 whitespace = false;
 470  248
             } else if (Character.isTitleCase(ch)) {
 471  4
                 buffer[i] = Character.toLowerCase(ch);
 472  4
                 whitespace = false;
 473  244
             } else if (Character.isLowerCase(ch)) {
 474  164
                 if (whitespace) {
 475  26
                     buffer[i] = Character.toTitleCase(ch);
 476  26
                     whitespace = false;
 477  
                 } else {
 478  138
                     buffer[i] = Character.toUpperCase(ch);
 479  
                 }
 480  
             } else {
 481  80
                 whitespace = Character.isWhitespace(ch);
 482  
             }
 483  
         }
 484  22
         return new String(buffer);
 485  
     }
 486  
 
 487  
     //-----------------------------------------------------------------------
 488  
     /**
 489  
      * <p>Extracts the initial characters from each word in the String.</p>
 490  
      * 
 491  
      * <p>All first characters after whitespace are returned as a new string.
 492  
      * Their case is not changed.</p>
 493  
      *
 494  
      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.
 495  
      * A <code>null</code> input String returns <code>null</code>.</p>
 496  
      *
 497  
      * <pre>
 498  
      * WordUtils.initials(null)             = null
 499  
      * WordUtils.initials("")               = ""
 500  
      * WordUtils.initials("Ben John Lee")   = "BJL"
 501  
      * WordUtils.initials("Ben J.Lee")      = "BJ"
 502  
      * </pre>
 503  
      *
 504  
      * @param str  the String to get initials from, may be null
 505  
      * @return String of initial letters, <code>null</code> if null String input
 506  
      * @see #initials(String,char[])
 507  
      * @since 2.2
 508  
      */
 509  
     public static String initials(final String str) {
 510  20
         return initials(str, null);
 511  
     }
 512  
 
 513  
     /**
 514  
      * <p>Extracts the initial characters from each word in the String.</p>
 515  
      * 
 516  
      * <p>All first characters after the defined delimiters are returned as a new string.
 517  
      * Their case is not changed.</p>
 518  
      *
 519  
      * <p>If the delimiters array is null, then Whitespace is used.
 520  
      * Whitespace is defined by {@link Character#isWhitespace(char)}.
 521  
      * A <code>null</code> input String returns <code>null</code>.
 522  
      * An empty delimiter array returns an empty String.</p>
 523  
      *
 524  
      * <pre>
 525  
      * WordUtils.initials(null, *)                = null
 526  
      * WordUtils.initials("", *)                  = ""
 527  
      * WordUtils.initials("Ben John Lee", null)   = "BJL"
 528  
      * WordUtils.initials("Ben J.Lee", null)      = "BJ"
 529  
      * WordUtils.initials("Ben J.Lee", [' ','.']) = "BJL"
 530  
      * WordUtils.initials(*, new char[0])         = ""
 531  
      * </pre>
 532  
      * 
 533  
      * @param str  the String to get initials from, may be null
 534  
      * @param delimiters  set of characters to determine words, null means whitespace
 535  
      * @return String of initial characters, <code>null</code> if null String input
 536  
      * @see #initials(String)
 537  
      * @since 2.2
 538  
      */
 539  
     public static String initials(final String str, final char... delimiters) {
 540  158
         if (StringUtils.isEmpty(str)) {
 541  28
             return str;
 542  
         }
 543  130
         if (delimiters != null && delimiters.length == 0) {
 544  20
             return StringUtils.EMPTY;
 545  
         }
 546  110
         final int strLen = str.length();
 547  110
         final char[] buf = new char[strLen / 2 + 1];
 548  110
         int count = 0;
 549  110
         boolean lastWasGap = true;
 550  1052
         for (int i = 0; i < strLen; i++) {
 551  942
             final char ch = str.charAt(i);
 552  
 
 553  942
             if (isDelimiter(ch, delimiters)) {
 554  240
                 lastWasGap = true;
 555  702
             } else if (lastWasGap) {
 556  218
                 buf[count++] = ch;
 557  218
                 lastWasGap = false;
 558  
             } else {
 559  
                 continue; // ignore ch
 560  
             }
 561  
         }
 562  110
         return new String(buf, 0, count);
 563  
     }
 564  
 
 565  
     //-----------------------------------------------------------------------
 566  
     /**
 567  
      * <p>Checks if the String contains all words in the given array.</p>
 568  
      *
 569  
      * <p>
 570  
      * A {@code null} String will return {@code false}. A {@code null}, zero
 571  
      * length search array or if one element of array is null will return {@code false}.
 572  
      * </p>
 573  
      *
 574  
      * <pre>
 575  
      * WordUtils.containsAllWords(null, *)            = false
 576  
      * WordUtils.containsAllWords("", *)              = false
 577  
      * WordUtils.containsAllWords(*, null)            = false
 578  
      * WordUtils.containsAllWords(*, [])              = false
 579  
      * WordUtils.containsAllWords("abcd", "ab", "cd") = false
 580  
      * WordUtils.containsAllWords("abc def", "def", "abc") = true
 581  
      * </pre>
 582  
      *
 583  
      *
 584  
      * @param word The CharSequence to check, may be null
 585  
      * @param words The array of String words to search for, may be null
 586  
      * @return {@code true} if all search words are found, {@code false} otherwise
 587  
      */
 588  
     public static boolean containsAllWords(CharSequence word, CharSequence... words) {
 589  28
         if (StringUtils.isEmpty(word) || ArrayUtils.isEmpty(words)) {
 590  12
             return false;
 591  
         }
 592  26
         for (CharSequence w : words) {
 593  24
             if (StringUtils.isBlank(w)) {
 594  8
                 return false;
 595  
             }
 596  16
             Pattern p = Pattern.compile(".*\\b" + w + "\\b.*");
 597  16
             if (!p.matcher(word).matches()) {
 598  6
                 return false;
 599  
             }
 600  
         }
 601  2
         return true;
 602  
     }
 603  
 
 604  
     //-----------------------------------------------------------------------
 605  
     /**
 606  
      * Is the character a delimiter.
 607  
      *
 608  
      * @param ch  the character to check
 609  
      * @param delimiters  the delimiters
 610  
      * @return true if it is a delimiter
 611  
      */
 612  
     private static boolean isDelimiter(final char ch, final char[] delimiters) {
 613  1710
         if (delimiters == null) {
 614  724
             return Character.isWhitespace(ch);
 615  
         }
 616  3444
         for (final char delimiter : delimiters) {
 617  2674
             if (ch == delimiter) {
 618  216
                 return true;
 619  
             }
 620  
         }
 621  770
         return false;
 622  
     }
 623  
 
 624  
 }