StringUtils_英文

来源:互联网 发布:进口软件涉及的税种 编辑:程序博客网 时间:2024/05/01 17:55

001/*

002 * Licensed to the Apache SoftwareFoundation (ASF) under one or more

003 * contributor license agreements.  See the NOTICE file distributed with

004 * this work for additional informationregarding copyright ownership.

005 * The ASF licenses this file to Youunder the Apache License, Version 2.0

006 * (the "License"); you maynot 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 oragreed to in writing, software

012 * distributed under the License isdistributed on an "AS IS" BASIS,

013 * WITHOUT WARRANTIES OR CONDITIONS OFANY KIND, either express or implied.

014 * See the License for the specificlanguage governing permissions and

015 * limitations under the License.

016 */

017package org.apache.commons.lang3;

018

019import java.io.UnsupportedEncodingException;

020import java.nio.charset.Charset;

021import java.text.Normalizer;

022import java.util.ArrayList;

023import java.util.Arrays;

024import java.util.Iterator;

025import java.util.List;

026import java.util.Locale;

027import java.util.Objects;

028import java.util.regex.Pattern;

029

030/**

031 * <p>Operations on {@linkjava.lang.String} that are

032 * {@code null} safe.</p>

033 *

034 * <ul>

035 * <li><b>IsEmpty/IsBlank</b>

036 *     - checks if a String contains text</li>

037 * <li><b>Trim/Strip</b>

038 *     - removes leading and trailing whitespace</li>

039 * <li><b>Equals/Compare</b>

040 *     - compares two strings null-safe</li>

041 * <li><b>startsWith</b>

042 *     - check if a String starts with a prefix null-safe</li>

043 * <li><b>endsWith</b>

044 *     - check if a String ends with a suffix null-safe</li>

045 * <li><b>IndexOf/LastIndexOf/Contains</b>

046 *     - null-safe index-of checks

047 * <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>

048 *     - index-of any of a set of Strings</li>

049 * <li><b>ContainsOnly/ContainsNone/ContainsAny</b>

050 *     - does String contains only/none/any of these characters</li>

051 * <li><b>Substring/Left/Right/Mid</b>

052 *     - null-safe substring extractions</li>

053 * <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>

054 *     - substring extraction relative to other strings</li>

055 * <li><b>Split/Join</b>

056 *     - splits a String into an array of substrings and vice versa</li>

057 * <li><b>Remove/Delete</b>

058 *     - removes part of a String</li>

059 * <li><b>Replace/Overlay</b>

060 *     - Searches a String and replaces one String with another</li>

061 * <li><b>Chomp/Chop</b>

062 *     - removes the last part of a String</li>

063 * <li><b>AppendIfMissing</b>

064 *     - appends a suffix to the end of the String if not present</li>

065 * <li><b>PrependIfMissing</b>

066 *     - prepends a prefix to the start of the String if not present</li>

067 * <li><b>LeftPad/RightPad/Center/Repeat</b>

068 *     - pads a String</li>

069 * <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>

070 *     - changes the case of a String</li>

071 * <li><b>CountMatches</b>

072 *     - counts the number of occurrences of one String in another</li>

073 * <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>

074 *     - checks the characters in a String</li>

075 * <li><b>DefaultString</b>

076 *     - protects against a null input String</li>

077 * <li><b>Rotate</b>

078 *     - rotate (circular shift) a String</li>

079 * <li><b>Reverse/ReverseDelimited</b>

080 *     - reverses a String</li>

081 * <li><b>Abbreviate</b>

082 *     - abbreviates a string using ellipsis or another given String</li>

083 * <li><b>Difference</b>

084 *     - compares Strings and reports on their differences</li>

085 * <li><b>LevenshteinDistance</b>

086 *     - the number of changes needed to change one String intoanother</li>

087 * </ul>

088 *

089 * <p>The {@code StringUtils}class defines certain words related to

090 * String handling.</p>

091 *

092 * <ul>

093 * <li>null - {@code null}</li>

094 * <li>empty - a zero-length string ({@code ""})</li>

095 * <li>space - the space character ({@code ' '}, char 32)</li>

096 * <li>whitespace - the characters defined by {@linkCharacter#isWhitespace(char)}</li>

097 * <li>trim - the characters &lt;= 32 as in {@linkString#trim()}</li>

098 * </ul>

099 *

100 * <p>{@code StringUtils} handles{@code null} input Strings quietly.

101 * That is to say that a {@code null}input will return {@code null}.

102 * Where a {@code boolean} or {@codeint} is being returned

103 * details vary by method.</p>

104 *

105 * <p>A side effect of the {@codenull} handling is that a

106 * {@code NullPointerException} shouldbe considered a bug in

107 * {@code StringUtils}.</p>

108 *

109 * <p>Methods in this class givesample code to explain their operation.

110 * The symbol {@code *} is used toindicate any input including {@code null}.</p>

111 *

112 * <p>#ThreadSafe#</p>

113 * @see java.lang.String

114 * @since 1.0

115 */

116//@Immutable

117public class StringUtils {

118   // Performance testing notes (JDK 1.4, Jul03, scolebourne)

119   // Whitespace:

120   // Character.isWhitespace() is faster than WHITESPACE.indexOf()

121   // where WHITESPACE is a string of all whitespace characters

122   //

123   // Character access:

124   // String.charAt(n) versus toCharArray(), then array[n]

125   // String.charAt(n) is about 15% worse for a 10K string

126   // They are about equal for a length 50 string

127   // String.charAt(n) is about 4 times better for a length 3 string

128   // String.charAt(n) is best bet overall

129   //

130   // Append:

131   // String.concat about twice as fast as StringBuffer.append

132   // (not sure who tested this)

133

134   /**

135    * A String for a space character.

136    *

137    * @since 3.2

138    */

139   public static final String SPACE = " ";

140

141   /**

142    * The empty String {@code ""}.

143    * @since 2.0

144    */

145   public static final String EMPTY = "";

146

147   /**

148    * A String for linefeed LF ("\n").

149    *

150    * @see <ahref="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF:Escape Sequences

151    *      for Character and StringLiterals</a>

152    * @since 3.2

153    */

154   public static final String LF = "\n";

155

156   /**

157    * A String for carriage return CR ("\r").

158    *

159    * @see <ahref="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6">JLF:Escape Sequences

160    *      for Character and StringLiterals</a>

161    * @since 3.2

162    */

163   public static final String CR = "\r";

164

165   /**

166    * Represents a failed index search.

167    * @since 2.1

168    */

169   public static final int INDEX_NOT_FOUND = -1;

170

171   /**

172    * <p>The maximum size to which the padding constant(s) canexpand.</p>

173    */

174   private static final int PAD_LIMIT = 8192;

175

176   /**

177    * <p>{@code StringUtils} instances should NOT be constructed in

178    * standard programming. Instead, the class should be used as

179    * {@code StringUtils.trim(" foo ");}.</p>

180    *

181    * <p>This constructor is public to permit tools that require aJavaBean

182    * instance to operate.</p>

183    */

184   public StringUtils() {

185       super();

186   }

187

188   // Empty checks

189   //-----------------------------------------------------------------------

190   /**

191    * <p>Checks if a CharSequence is empty ("") ornull.</p>

192    *

193    * <pre>

194    * StringUtils.isEmpty(null)      =true

195    * StringUtils.isEmpty("")        = true

196    * StringUtils.isEmpty(" ")       = false

197    * StringUtils.isEmpty("bob")     = false

198    * StringUtils.isEmpty(" bob  ") = false

199    * </pre>

200    *

201    * <p>NOTE: This method changed in Lang version 2.0.

202    * It no longer trims the CharSequence.

203    * That functionality is available in isBlank().</p>

204    *

205    * @param cs  the CharSequence tocheck, may be null

206    * @return {@code true} if the CharSequence is empty or null

207    * @since 3.0 Changed signature from isEmpty(String) toisEmpty(CharSequence)

208    */

209   public static boolean isEmpty(final CharSequence cs) {

210       return cs == null || cs.length() == 0;

211   }

212

213   /**

214    * <p>Checks if a CharSequence is not empty ("") and notnull.</p>

215    *

216    * <pre>

217    * StringUtils.isNotEmpty(null)     = false

218    * StringUtils.isNotEmpty("")        = false

219    * StringUtils.isNotEmpty(" ")       = true

220    * StringUtils.isNotEmpty("bob")     = true

221    * StringUtils.isNotEmpty(" bob  ") = true

222    * </pre>

223    *

224    * @param cs  the CharSequence tocheck, may be null

225    * @return {@code true} if the CharSequence is not empty and not null

226    * @since 3.0 Changed signature from isNotEmpty(String) toisNotEmpty(CharSequence)

227    */

228   public static boolean isNotEmpty(final CharSequence cs) {

229       return !isEmpty(cs);

230   }

231

232   /**

233    * <p>Checks if any of the CharSequences are empty ("")or null.</p>

234    *

235    * <pre>

236    * StringUtils.isAnyEmpty(null)             = true

237    * StringUtils.isAnyEmpty(null, "foo")      = true

238    * StringUtils.isAnyEmpty("", "bar")        = true

239    * StringUtils.isAnyEmpty("bob", "")        = true

240    * StringUtils.isAnyEmpty(" bob  ", null)  = true

241    * StringUtils.isAnyEmpty(" ", "bar")       = false

242    * StringUtils.isAnyEmpty("foo", "bar")     = false

243    * StringUtils.isAnyEmpty(new String[]{})   = false

244    * StringUtils.isAnyEmpty(new String[]{""}) = true

245    * </pre>

246    *

247    * @param css  the CharSequences tocheck, may be null or empty

248    * @return {@code true} if any of the CharSequences are empty or null

249    * @since 3.2

250    */

251   public static boolean isAnyEmpty(final CharSequence... css) {

252     if (ArrayUtils.isEmpty(css)) {

253       return false;

254     }

255     for (final CharSequence cs : css){

256       if (isEmpty(cs)) {

257         return true;

258       }

259     }

260     return false;

261   }

262

263   /**

264    * <p>Checks if none of the CharSequences are empty ("")or null.</p>

265    *

266    * <pre>

267    * StringUtils.isNoneEmpty(null)             = false

268    * StringUtils.isNoneEmpty(null, "foo")      = false

269    * StringUtils.isNoneEmpty("", "bar")        =false

270    * StringUtils.isNoneEmpty("bob", "")        = false

271    * StringUtils.isNoneEmpty(" bob  ", null)  = false

272    * StringUtils.isNoneEmpty(new String[] {})  = true

273    * StringUtils.isNoneEmpty(new String[]{""}) = false

274    * StringUtils.isNoneEmpty(" ", "bar")       = true

275    * StringUtils.isNoneEmpty("foo", "bar")     = true

276    * </pre>

277    *

278    * @param css  the CharSequences tocheck, may be null or empty

279    * @return {@code true} if none of the CharSequences are empty or null

280    * @since 3.2

281    */

282   public static boolean isNoneEmpty(final CharSequence... css) {

283     return !isAnyEmpty(css);

284   }

285

286   /**

287    * <p>Checks if all of the CharSequences are empty ("")or null.</p>

288    *

289    * <pre>

290    * StringUtils.isAllEmpty(null)             = true

291    * StringUtils.isAllEmpty(null, "")         = true

292    * StringUtils.isAllEmpty(new String[] {})  = true

293    * StringUtils.isAllEmpty(null, "foo")      = false

294    * StringUtils.isAllEmpty("", "bar")        = false

295    * StringUtils.isAllEmpty("bob", "")        = false

296    * StringUtils.isAllEmpty(" bob  ", null)  = false

297    * StringUtils.isAllEmpty(" ", "bar")       = false

298    * StringUtils.isAllEmpty("foo", "bar")     = false

299    * </pre>

300    *

301    * @param css  the CharSequences tocheck, may be null or empty

302    * @return {@code true} if all of the CharSequences are empty or null

303    * @since 3.6

304    */

305   public static boolean isAllEmpty(final CharSequence... css) {

306       if (ArrayUtils.isEmpty(css)) {

307            return true;

308       }

309       for (final CharSequence cs : css) {

310            if (isNotEmpty(cs)) {

311                return false;

312            }

313       }

314       return true;

315   }

316

317   /**

318    * <p>Checks if a CharSequence is empty (""), null orwhitespace only.</p>

319    *

320    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

321    *

322    * <pre>

323    * StringUtils.isBlank(null)      =true

324    * StringUtils.isBlank("")        = true

325    * StringUtils.isBlank(" ")       = true

326    * StringUtils.isBlank("bob")     = false

327    * StringUtils.isBlank(" bob  ") = false

328    * </pre>

329    *

330    * @param cs  the CharSequence tocheck, may be null

331    * @return {@code true} if the CharSequence is null, empty or whitespaceonly

332    * @since 2.0

333    * @since 3.0 Changed signature from isBlank(String) toisBlank(CharSequence)

334    */

335   public static boolean isBlank(final CharSequence cs) {

336       int strLen;

337       if (cs == null || (strLen = cs.length()) == 0) {

338            return true;

339       }

340       for (int i = 0; i < strLen; i++) {

341            if(Character.isWhitespace(cs.charAt(i)) == false) {

342               return false;

343            }

344       }

345       return true;

346   }

347

348   /**

349    * <p>Checks if a CharSequence is not empty (""), notnull and not whitespace only.</p>

350    *

351    * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>

352    *

353    * <pre>

354    * StringUtils.isNotBlank(null)     = false

355    * StringUtils.isNotBlank("")        = false

356    * StringUtils.isNotBlank(" ")       = false

357    * StringUtils.isNotBlank("bob")     = true

358    * StringUtils.isNotBlank(" bob  ") = true

359    * </pre>

360    *

361    * @param cs  the CharSequence tocheck, may be null

362    * @return {@code true} if the CharSequence is

363    *  not empty and not null and notwhitespace only

364    * @since 2.0

365    * @since 3.0 Changed signature from isNotBlank(String) toisNotBlank(CharSequence)

366    */

367   public static boolean isNotBlank(final CharSequence cs) {

368       return !isBlank(cs);

369   }

370

371   /**

372    * <p>Checks if any of the CharSequences are empty ("")or null or whitespace only.</p>

373    *

374    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

375    *

376    * <pre>

377    * StringUtils.isAnyBlank(null)             = true

378    * StringUtils.isAnyBlank(null, "foo")      = true

379    * StringUtils.isAnyBlank(null, null)       = true

380    * StringUtils.isAnyBlank("", "bar")        = true

381    * StringUtils.isAnyBlank("bob", "")        = true

382    * StringUtils.isAnyBlank(" bob  ", null)  = true

383    * StringUtils.isAnyBlank(" ", "bar")       = true

384    * StringUtils.isAnyBlank(new String[] {})  = false

385    * StringUtils.isAnyBlank(new String[]{""}) = true

386    * StringUtils.isAnyBlank("foo", "bar")     = false

387    * </pre>

388    *

389    * @param css  the CharSequences tocheck, may be null or empty

390    * @return {@code true} if any of the CharSequences are empty or null orwhitespace only

391    * @since 3.2

392    */

393   public static boolean isAnyBlank(final CharSequence... css) {

394     if (ArrayUtils.isEmpty(css)) {

395       return false;

396     }

397     for (final CharSequence cs : css){

398       if (isBlank(cs)) {

399         return true;

400       }

401     }

402     return false;

403   }

404

405   /**

406    * <p>Checks if none of the CharSequences are empty (""),null or whitespace only.</p>

407    *

408    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

409    *

410    * <pre>

411    * StringUtils.isNoneBlank(null)             = false

412    * StringUtils.isNoneBlank(null, "foo")      = false

413    * StringUtils.isNoneBlank(null, null)       = false

414    * StringUtils.isNoneBlank("", "bar")        = false

415    * StringUtils.isNoneBlank("bob", "")        = false

416    * StringUtils.isNoneBlank(" bob  ", null)  = false

417    * StringUtils.isNoneBlank(" ", "bar")       = false

418    * StringUtils.isNoneBlank(new String[] {})  = true

419    * StringUtils.isNoneBlank(new String[]{""}) = false

420    * StringUtils.isNoneBlank("foo", "bar")     = true

421    * </pre>

422    *

423    * @param css  the CharSequences tocheck, may be null or empty

424    * @return {@code true} if none of the CharSequences are empty or null orwhitespace only

425    * @since 3.2

426    */

427   public static boolean isNoneBlank(final CharSequence... css) {

428     return !isAnyBlank(css);

429   }

430

431   /**

432    * <p>Checks if all of the CharSequences are empty (""),null or whitespace only.</p>

433    *

434    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

435    *

436    * <pre>

437    * StringUtils.isAllBlank(null)             = true

438    * StringUtils.isAllBlank(null, "foo")      = false

439    * StringUtils.isAllBlank(null, null)       = true

440    * StringUtils.isAllBlank("", "bar")        = false

441    * StringUtils.isAllBlank("bob", "")        =false

442    * StringUtils.isAllBlank(" bob  ", null)  = false

443    * StringUtils.isAllBlank(" ", "bar")       = false

444    * StringUtils.isAllBlank("foo", "bar")     = false

445    * StringUtils.isAllBlank(new String[] {})  = true

446    * </pre>

447    *

448    * @param css  the CharSequences tocheck, may be null or empty

449    * @return {@code true} if all of the CharSequences are empty or null orwhitespace only

450    * @since 3.6

451    */

452   public static boolean isAllBlank(final CharSequence... css) {

453       if (ArrayUtils.isEmpty(css)) {

454            return true;

455       }

456       for (final CharSequence cs : css) {

457            if (isNotBlank(cs)) {

458               return false;

459            }

460       }

461       return true;

462   }

463

464   // Trim

465   //-----------------------------------------------------------------------

466   /**

467    * <p>Removes control characters (char &lt;= 32) from both

468    * ends of this String, handling{@code null} by returning

469    * {@code null}.</p>

470    *

471    * <p>The String is trimmed using {@link String#trim()}.

472    * Trim removes start and end characters &lt;= 32.

473    * To strip whitespace use {@link #strip(String)}.</p>

474    *

475    * <p>To trim your choice of characters, use the

476    * {@link #strip(String, String)} methods.</p>

477    *

478    * <pre>

479    * StringUtils.trim(null)         = null

480    * StringUtils.trim("")            = ""

481    * StringUtils.trim("    ")       = ""

482    * StringUtils.trim("abc")         = "abc"

483    * StringUtils.trim("   abc    ") = "abc"

484    * </pre>

485    *

486    * @param str  the String to betrimmed, may be null

487    * @return the trimmed string, {@code null} if null String input

488    */

489   public static String trim(final String str) {

490       return str == null ? null : str.trim();

491   }

492

493   /**

494    * <p>Removes control characters (char &lt;= 32) from both

495    * ends of this String returning {@code null} if the String is

496    * empty ("") after the trim or if it is {@code null}.

497    *

498    * <p>The String is trimmed using {@link String#trim()}.

499    * Trim removes start and end characters &lt;= 32.

500    * To strip whitespace use {@link #stripToNull(String)}.</p>

501    *

502    * <pre>

503    * StringUtils.trimToNull(null)         = null

504    * StringUtils.trimToNull("")            = null

505    * StringUtils.trimToNull("    ")       = null

506    * StringUtils.trimToNull("abc")         = "abc"

507    * StringUtils.trimToNull("   abc    ") = "abc"

508    * </pre>

509    *

510     * @param str the String to be trimmed, may be null

511    * @return the trimmed String,

512    *  {@code null} if only chars&lt;= 32, empty or null String input

513    * @since 2.0

514    */

515   public static String trimToNull(final String str) {

516       final String ts = trim(str);

517       return isEmpty(ts) ? null : ts;

518   }

519

520   /**

521    * <p>Removes control characters (char &lt;= 32) from both

522    * ends of this String returning an empty String ("") if theString

523    * is empty ("") after the trim or if it is {@code null}.

524    *

525    * <p>The String is trimmed using {@link String#trim()}.

526    * Trim removes start and end characters &lt;= 32.

527    * To strip whitespace use {@link #stripToEmpty(String)}.</p>

528    *

529    * <pre>

530    * StringUtils.trimToEmpty(null)         = ""

531    * StringUtils.trimToEmpty("")            = ""

532    * StringUtils.trimToEmpty("    ")       = ""

533    * StringUtils.trimToEmpty("abc")         = "abc"

534    * StringUtils.trimToEmpty("   abc    ") = "abc"

535    * </pre>

536    *

537    * @param str  the String to betrimmed, may be null

538    * @return the trimmed String, or an empty String if {@code null} input

539    * @since 2.0

540    */

541    public static String trimToEmpty(finalString str) {

542       return str == null ? EMPTY : str.trim();

543   }

544

545   /**

546    * <p>Truncates a String. This will turn

547    * "Now is the time for all good men" into "Now is thetime for".</p>

548    *

549    * <p>Specifically:</p>

550    * <ul>

551    *   <li>If {@code str} isless than {@code maxWidth} characters

552    *       long, returnit.</li>

553    *   <li>Else truncate it to{@code substring(str, 0, maxWidth)}.</li>

554    *   <li>If {@code maxWidth} is less than{@code 0}, throw an

555    *       {@codeIllegalArgumentException}.</li>

556    *   <li>In no case will itreturn a String of length greater than

557    *       {@codemaxWidth}.</li>

558    * </ul>

559    *

560     * <pre>

561    * StringUtils.truncate(null, 0)      = null

562    * StringUtils.truncate(null, 2)      = null

563    * StringUtils.truncate("", 4)         = ""

564    * StringUtils.truncate("abcdefg", 4)  = "abcd"

565    * StringUtils.truncate("abcdefg", 6)  = "abcdef"

566    * StringUtils.truncate("abcdefg", 7)  = "abcdefg"

567    * StringUtils.truncate("abcdefg", 8)  = "abcdefg"

568    * StringUtils.truncate("abcdefg", -1) = throws anIllegalArgumentException

569    * </pre>

570    *

571    * @param str  the String totruncate, may be null

572    * @param maxWidth  maximum lengthof result String, must be positive

573    * @return truncated String, {@code null} if null String input

574    * @since 3.5

575    */

576   public static String truncate(final String str, final int maxWidth) {

577       return truncate(str, 0, maxWidth);

578   }

579

580   /**

581    * <p>Truncates a String. This will turn

582    * "Now is the time for all good men" into "is the time forall".</p>

583    *

584    * <p>Works like {@code truncate(String, int)}, but allows you tospecify

585    * a "left edge" offset.

586    *

587    * <p>Specifically:</p>

588    * <ul>

589    *   <li>If {@code str} isless than {@code maxWidth} characters

590    *       long, returnit.</li>

591    *   <li>Else truncate it to{@code substring(str, offset, maxWidth)}.</li>

592    *   <li>If {@code maxWidth}is less than {@code 0}, throw an

593    *       {@codeIllegalArgumentException}.</li>

594    *   <li>If {@code offset} isless than {@code 0}, throw an

595    *       {@codeIllegalArgumentException}.</li>

596    *   <li>In no case will itreturn a String of length greater than

597    *       {@codemaxWidth}.</li>

598    * </ul>

599    *

600    * <pre>

601    * StringUtils.truncate(null, 0, 0) = null

602    * StringUtils.truncate(null, 2, 4) = null

603    * StringUtils.truncate("", 0, 10) = ""

604    * StringUtils.truncate("", 2, 10) = ""

605    * StringUtils.truncate("abcdefghij", 0, 3) = "abc"

606    * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"

607    * StringUtils.truncate("raspberry peach", 10, 15) ="peach"

608    * StringUtils.truncate("abcdefghijklmno", 0, 10) ="abcdefghij"

609    * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws anIllegalArgumentException

610    * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE,10) = "abcdefghij"

611    * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE,Integer.MAX_VALUE) = "abcdefghijklmno"

612     *StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) ="abcdefghijklmno"

613    * StringUtils.truncate("abcdefghijklmno", 1, 10) ="bcdefghijk"

614    * StringUtils.truncate("abcdefghijklmno", 2, 10) ="cdefghijkl"

615    * StringUtils.truncate("abcdefghijklmno", 3, 10) ="defghijklm"

616    * StringUtils.truncate("abcdefghijklmno", 4, 10) ="efghijklmn"

617    * StringUtils.truncate("abcdefghijklmno", 5, 10) ="fghijklmno"

618    * StringUtils.truncate("abcdefghijklmno", 5, 5) ="fghij"

619    * StringUtils.truncate("abcdefghijklmno", 5, 3) ="fgh"

620    * StringUtils.truncate("abcdefghijklmno", 10, 3) ="klm"

621    * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE)= "klmno"

622    * StringUtils.truncate("abcdefghijklmno", 13, 1) ="n"

623    * StringUtils.truncate("abcdefghijklmno", 13,Integer.MAX_VALUE) = "no"

624    * StringUtils.truncate("abcdefghijklmno", 14, 1) ="o"

625    * StringUtils.truncate("abcdefghijklmno", 14,Integer.MAX_VALUE) = "o"

626    * StringUtils.truncate("abcdefghijklmno", 15, 1) =""

627    * StringUtils.truncate("abcdefghijklmno", 15,Integer.MAX_VALUE) = ""

628    * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE,Integer.MAX_VALUE) = ""

629    * StringUtils.truncate("abcdefghij", 3, -1) = throws anIllegalArgumentException

630    * StringUtils.truncate("abcdefghij", -2, 4) = throws anIllegalArgumentException

631    * </pre>

632    *

633    * @param str  the String to check,may be null

634    * @param offset  left edge ofsource String

635    * @param maxWidth  maximum lengthof result String, must be positive

636    * @return truncated String, {@code null} if null String input

637    * @since 3.5

638    */

639   public static String truncate(final String str, final int offset, finalint maxWidth) {

640       if (offset < 0) {

641            throw newIllegalArgumentException("offset cannot be negative");

642       }

643       if (maxWidth < 0) {

644            throw newIllegalArgumentException("maxWith cannot be negative");

645       }

646       if (str == null) {

647            return null;

648       }

649       if (offset > str.length()) {

650            return EMPTY;

651       }

652       if (str.length() > maxWidth) {

653            final int ix = offset + maxWidth> str.length() ? str.length() : offset + maxWidth;

654            return str.substring(offset, ix);

655       }

656       return str.substring(offset);

657   }

658

659   // Stripping

660   //-----------------------------------------------------------------------

661   /**

662    * <p>Strips whitespace from the start and end of aString.</p>

663    *

664    * <p>This is similar to {@link #trim(String)} but removes whitespace.

665    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

666    *

667    * <p>A {@code null} input String returns {@code null}.</p>

668    *

669    * <pre>

670    * StringUtils.strip(null)     =null

671    * StringUtils.strip("")      = ""

672    * StringUtils.strip("  ")    = ""

673    * StringUtils.strip("abc")   = "abc"

674    * StringUtils.strip(" abc")  = "abc"

675    * StringUtils.strip("abc ")  = "abc"

676    * StringUtils.strip(" abc ") = "abc"

677    * StringUtils.strip(" ab c ") = "ab c"

678    * </pre>

679    *

680    * @param str  the String to removewhitespace from, may be null

681    * @return the stripped String, {@code null} if null String input

682    */

683   public static String strip(final String str) {

684       return strip(str, null);

685   }

686

687   /**

688    * <p>Strips whitespace from the start and end of a String  returning

689    * {@code null} if the String is empty ("") after thestrip.</p>

690    *

691    * <p>This is similar to {@link #trimToNull(String)} but removeswhitespace.

692    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

693    *

694    * <pre>

695    * StringUtils.stripToNull(null)    = null

696    * StringUtils.stripToNull("")       = null

697    * StringUtils.stripToNull("  ")    = null

698    * StringUtils.stripToNull("abc")    = "abc"

699    * StringUtils.stripToNull(" abc")  = "abc"

700    * StringUtils.stripToNull("abc ")  = "abc"

701    * StringUtils.stripToNull(" abc ")  = "abc"

702    * StringUtils.stripToNull(" ab c ") = "ab c"

703    * </pre>

704    *

705    * @param str  the String to bestripped, may be null

706    * @return the stripped String,

707    *  {@code null} if whitespace,empty or null String input

708    * @since 2.0

709    */

710   public static String stripToNull(String str) {

711       if (str == null) {

712            return null;

713       }

714       str = strip(str, null);

715       return str.isEmpty() ? null : str;

716   }

717

718   /**

719    * <p>Strips whitespace from the start and end of a String  returning

720    * an empty String if {@code null} input.</p>

721    *

722    * <p>This is similar to {@link #trimToEmpty(String)} but removeswhitespace.

723    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

724    *

725    * <pre>

726    * StringUtils.stripToEmpty(null)    = ""

727    * StringUtils.stripToEmpty("")       = ""

728    * StringUtils.stripToEmpty("  ")    = ""

729    * StringUtils.stripToEmpty("abc")    = "abc"

730    * StringUtils.stripToEmpty(" abc")  = "abc"

731    * StringUtils.stripToEmpty("abc ")  = "abc"

732    * StringUtils.stripToEmpty(" abc ")  = "abc"

733    * StringUtils.stripToEmpty(" ab c ") = "ab c"

734    * </pre>

735    *

736    * @param str  the String to bestripped, may be null

737    * @return the trimmed String, or an empty String if {@code null} input

738    * @since 2.0

739    */

740   public static String stripToEmpty(final String str) {

741       return str == null ? EMPTY : strip(str, null);

742   }

743

744   /**

745    * <p>Strips any of a set of characters from the start and end of aString.

746    * This is similar to {@link String#trim()} but allows the characters

747    * to be stripped to be controlled.</p>

748    *

749    * <p>A {@code null} input String returns {@code null}.

750    * An empty string ("") input returns the emptystring.</p>

751    *

752    * <p>If the stripChars String is {@code null}, whitespace is

753    * stripped as defined by {@link Character#isWhitespace(char)}.

754    * Alternatively use {@link #strip(String)}.</p>

755    *

756    * <pre>

757    * StringUtils.strip(null, *)         = null

758    * StringUtils.strip("", *)            = ""

759    * StringUtils.strip("abc", null)      = "abc"

760    * StringUtils.strip(" abc", null)    ="abc"

761    * StringUtils.strip("abc ", null)    = "abc"

762    * StringUtils.strip(" abc ", null)    = "abc"

763    * StringUtils.strip(" abcyx", "xyz") = " abc"

764    * </pre>

765    *

766    * @param str  the String to removecharacters from, may be null

767    * @param stripChars  thecharacters to remove, null treated as whitespace

768    * @return the stripped String, {@code null} if null String input

769    */

770   public static String strip(String str, final String stripChars) {

771       if (isEmpty(str)) {

772            return str;

773       }

774       str = stripStart(str, stripChars);

775       return stripEnd(str, stripChars);

776   }

777

778   /**

779    * <p>Strips any of a set of characters from the start of aString.</p>

780    *

781    * <p>A {@code null} input String returns {@code null}.

782    * An empty string ("") input returns the emptystring.</p>

783    *

784    * <p>If the stripChars String is {@code null}, whitespace is

785    * stripped as defined by {@link Character#isWhitespace(char)}.</p>

786    *

787    * <pre>

788    * StringUtils.stripStart(null, *)          = null

789    * StringUtils.stripStart("", *)            = ""

790    * StringUtils.stripStart("abc", "")        = "abc"

791    * StringUtils.stripStart("abc", null)      = "abc"

792    * StringUtils.stripStart(" abc", null)    ="abc"

793    * StringUtils.stripStart("abc ", null)    = "abc  "

794    * StringUtils.stripStart(" abc ", null)    = "abc "

795    * StringUtils.stripStart("yxabc ", "xyz") = "abc "

796    * </pre>

797    *

798    * @param str  the String to removecharacters from, may be null

799    * @param stripChars  thecharacters to remove, null treated as whitespace

800    * @return the stripped String, {@code null} if null String input

801    */

802   public static String stripStart(final String str, final StringstripChars) {

803       int strLen;

804       if (str == null || (strLen = str.length()) == 0) {

805            return str;

806       }

807       int start = 0;

808       if (stripChars == null) {

809            while (start != strLen &&Character.isWhitespace(str.charAt(start))) {

810                start++;

811            }

812       } else if (stripChars.isEmpty()) {

813            return str;

814       } else {

815            while (start != strLen &&stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {

816                start++;

817            }

818       }

819       return str.substring(start);

820   }

821

822   /**

823    * <p>Strips any of a set of characters from the end of aString.</p>

824    *

825    * <p>A {@code null} input String returns {@code null}.

826    * An empty string ("") input returns the emptystring.</p>

827    *

828    * <p>If the stripChars String is {@code null}, whitespace is

829    * stripped as defined by {@link Character#isWhitespace(char)}.</p>

830    *

831    * <pre>

832    * StringUtils.stripEnd(null, *)         = null

833    * StringUtils.stripEnd("", *)            = ""

834    * StringUtils.stripEnd("abc", "")        = "abc"

835    * StringUtils.stripEnd("abc", null)      = "abc"

836    * StringUtils.stripEnd(" abc", null)    = "  abc"

837    * StringUtils.stripEnd("abc ", null)    = "abc"

838    * StringUtils.stripEnd(" abc ", null)    = " abc"

839    * StringUtils.stripEnd(" abcyx", "xyz") = " abc"

840    * StringUtils.stripEnd("120.00", ".0")   = "12"

841    * </pre>

842    *

843    * @param str  the String to removecharacters from, may be null

844    * @param stripChars  the set ofcharacters to remove, null treated as whitespace

845    * @return the stripped String, {@code null} if null String input

846    */

847   public static String stripEnd(final String str, final String stripChars){

848       int end;

849       if (str == null || (end = str.length()) == 0) {

850            return str;

851       }

852

853       if (stripChars == null) {

854            while (end != 0 &&Character.isWhitespace(str.charAt(end - 1))) {

855                end--;

856            }

857       } else if (stripChars.isEmpty()) {

858            return str;

859       } else {

860            while (end != 0 &&stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {

861                end--;

862            }

863       }

864       return str.substring(0, end);

865   }

866

867   // StripAll

868   //-----------------------------------------------------------------------

869   /**

870    * <p>Strips whitespace from the start and end of every String inan array.

871    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

872    *

873    * <p>A new array is returned each time, except for length zero.

874    * A {@code null} array will return {@code null}.

875    * An empty array will return itself.

876    * A {@code null} array entry will be ignored.</p>

877    *

878    * <pre>

879    * StringUtils.stripAll(null)            = null

880    * StringUtils.stripAll([])              = []

881    * StringUtils.stripAll(["abc", "  abc"]) = ["abc","abc"]

882    * StringUtils.stripAll(["abc ", null])  =["abc", null]

883    * </pre>

884    *

885    * @param strs  the array to removewhitespace from, may be null

886    * @return the stripped Strings, {@code null} if null array input

887    */

888   public static String[] stripAll(final String... strs) {

889       return stripAll(strs, null);

890   }

891

892   /**

893    * <p>Strips any of a set of characters from the start and end ofevery

894    * String in an array.</p>

895    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

896    *

897    * <p>A new array is returned each time, except for length zero.

898    * A {@code null} array will return {@code null}.

899    * An empty array will return itself.

900    * A {@code null} array entry will be ignored.

901    * A {@code null} stripChars will strip whitespace as defined by

902    * {@link Character#isWhitespace(char)}.</p>

903    *

904    * <pre>

905    * StringUtils.stripAll(null, *)                = null

906    * StringUtils.stripAll([], *)                  = []

907    * StringUtils.stripAll(["abc", "  abc"], null) = ["abc","abc"]

908    * StringUtils.stripAll(["abc ", null], null)  =["abc", null]

909    * StringUtils.stripAll(["abc ", null], "yz")  =["abc  ", null]

910    * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]

911    * </pre>

912    *

913    * @param strs  the array to removecharacters from, may be null

914    * @param stripChars  thecharacters to remove, null treated as whitespace

915    * @return the stripped Strings, {@code null} if null array input

916    */

917   public static String[] stripAll(final String[] strs, final StringstripChars) {

918       int strsLen;

919       if (strs == null || (strsLen = strs.length) == 0) {

920            return strs;

921       }

922       final String[] newArr = new String[strsLen];

923       for (int i = 0; i < strsLen; i++) {

924            newArr[i] = strip(strs[i],stripChars);

925       }

926       return newArr;

927   }

928

929   /**

930    * <p>Removes diacritics (~= accents) from a string. The case willnot be altered.</p>

931    * <p>For instance, '&agrave;' will be replaced by'a'.</p>

932    * <p>Note that ligatures will be left as is.</p>

933    *

934    * <pre>

935    * StringUtils.stripAccents(null)                = null

936    * StringUtils.stripAccents("")                  = ""

937    * StringUtils.stripAccents("control")           = "control"

938    * StringUtils.stripAccents("&eacute;clair")     = "eclair"

939    * </pre>

940    *

941    * @param input String to be stripped

942    * @return input text with diacritics removed

943    *

944    * @since 3.0

945    */

946   // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replacesaccented characters by their unaccented equivalent (and uncommitted bug fix:https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).

947   public static String stripAccents(final String input) {

948       if(input == null) {

949            return null;

950       }

951       final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");//$NON-NLS-1$

952       final StringBuilder decomposed = newStringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));

953       convertRemainingAccentCharacters(decomposed);

954       // Note that this doesn't correctly remove ligatures...

955       return pattern.matcher(decomposed).replaceAll(StringUtils.EMPTY);

956   }

957

958   private static void convertRemainingAccentCharacters(final StringBuilderdecomposed) {

959       for (int i = 0; i <decomposed.length(); i++) {

960            if (decomposed.charAt(i) =='\u0141') {

961                decomposed.deleteCharAt(i);

962                decomposed.insert(i, 'L');

963            } else if (decomposed.charAt(i) =='\u0142') {

964                decomposed.deleteCharAt(i);

965                decomposed.insert(i, 'l');

966            }

967       }

968   }

969

970   // Equals

971   //-----------------------------------------------------------------------

972   /**

973    * <p>Compares twoCharSequences, returning {@code true} if they represent

974    * equal sequences of characters.</p>

975    *

976    * <p>{@code null}s are handled without exceptions. Two {@codenull}

977    * references are considered to be equal. The comparison is casesensitive.</p>

978    *

979    * <pre>

980    * StringUtils.equals(null, null)  = true

981    * StringUtils.equals(null, "abc")  = false

982    * StringUtils.equals("abc", null)  = false

983    * StringUtils.equals("abc", "abc") = true

984    * StringUtils.equals("abc", "ABC") = false

985    * </pre>

986    *

987    * @see Object#equals(Object)

988    * @param cs1  the firstCharSequence, may be {@code null}

989    * @param cs2  the secondCharSequence, may be {@code null}

990    * @return {@code true} if the CharSequences are equal (case-sensitive),or both {@code null}

991    * @since 3.0 Changed signature from equals(String, String) toequals(CharSequence, CharSequence)

992    */

993   public static boolean equals(final CharSequence cs1, final CharSequencecs2) {

994       if (cs1 == cs2) {

995            return true;

996       }

997       if (cs1 == null || cs2 == null) {

998            return false;

999       }

1000       if (cs1.length() != cs2.length()) {

1001            return false;

1002       }

1003       if (cs1 instanceof String && cs2 instanceof String) {

1004            return cs1.equals(cs2);

1005       }

1006       return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0,cs1.length());

1007   }

1008

1009   /**

1010    * <p>Compares two CharSequences, returning {@code true} if theyrepresent

1011    * equal sequences of characters, ignoring case.</p>

1012    *

1013    * <p>{@code null}s are handled without exceptions. Two {@codenull}

1014    * references are considered equal. Comparison is caseinsensitive.</p>

1015    *

1016    * <pre>

1017    * StringUtils.equalsIgnoreCase(null, null)   = true

1018    * StringUtils.equalsIgnoreCase(null, "abc")  = false

1019    * StringUtils.equalsIgnoreCase("abc", null)  = false

1020    * StringUtils.equalsIgnoreCase("abc", "abc") = true

1021    * StringUtils.equalsIgnoreCase("abc", "ABC") = true

1022    * </pre>

1023    *

1024    * @param str1  the firstCharSequence, may be null

1025    * @param str2  the secondCharSequence, may be null

1026    * @return {@code true} if the CharSequence are equal, case insensitive,or

1027    *  both {@code null}

1028    * @since 3.0 Changed signature from equalsIgnoreCase(String, String) toequalsIgnoreCase(CharSequence, CharSequence)

1029    */

1030   public static boolean equalsIgnoreCase(final CharSequence str1, finalCharSequence str2) {

1031       if (str1 == null || str2 == null) {

1032            return str1 == str2;

1033       } else if (str1 == str2) {

1034            return true;

1035       } else if (str1.length() != str2.length()) {

1036            return false;

1037       } else {

1038           returnCharSequenceUtils.regionMatches(str1, true, 0, str2, 0, str1.length());

1039       }

1040   }

1041

1042   // Compare

1043   //-----------------------------------------------------------------------

1044   /**

1045    * <p>Compare two Strings lexicographically, as per {@linkString#compareTo(String)}, returning :</p>

1046    * <ul>

1047    *  <li>{@code int = 0}, if{@code str1} is equal to {@code str2} (or both {@code null})</li>

1048    *  <li>{@code int < 0},if {@code str1} is less than {@code str2}</li>

1049    *  <li>{@code int > 0},if {@code str1} is greater than {@code str2}</li>

1050    * </ul>

1051    *

1052    * <p>This is a {@code null} safe version of :</p>

1053    *<blockquote><pre>str1.compareTo(str2)</pre></blockquote>

1054    *

1055    * <p>{@code null} value is considered less than non-{@code null}value.

1056    * Two {@code null} references are considered equal.</p>

1057    *

1058    * <pre>

1059    * StringUtils.compare(null, null)  = 0

1060    * StringUtils.compare(null , "a")   &lt; 0

1061    * StringUtils.compare("a", null)    &gt; 0

1062    * StringUtils.compare("abc", "abc") = 0

1063    * StringUtils.compare("a", "b")     &lt; 0

1064    * StringUtils.compare("b", "a")     &gt; 0

1065    * StringUtils.compare("a", "B")     &gt; 0

1066    * StringUtils.compare("ab", "abc")  &lt; 0

1067    * </pre>

1068    *

1069    * @see #compare(String, String, boolean)

1070    * @see String#compareTo(String)

1071    * @param str1  the String tocompare from

1072    * @param str2  the String tocompare to

1073    * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectivelyless, equal or greater than {@code str2}

1074    * @since 3.5

1075    */

1076   public static int compare(final String str1, final String str2) {

1077       return compare(str1, str2, true);

1078   }

1079

1080   /**

1081    * <p>Compare two Strings lexicographically, as per {@linkString#compareTo(String)}, returning :</p>

1082    * <ul>

1083    *  <li>{@code int = 0}, if{@code str1} is equal to {@code str2} (or both {@code null})</li>

1084    *  <li>{@code int < 0},if {@code str1} is less than {@code str2}</li>

1085    *  <li>{@code int > 0},if {@code str1} is greater than {@code str2}</li>

1086    * </ul>

1087    *

1088    * <p>This is a {@code null} safe version of :</p>

1089    *<blockquote><pre>str1.compareTo(str2)</pre></blockquote>

1090    *

1091    * <p>{@code null} inputs are handled according to the {@codenullIsLess} parameter.

1092    * Two {@code null} references are considered equal.</p>

1093    *

1094    * <pre>

1095    * StringUtils.compare(null, null, *)    = 0

1096    * StringUtils.compare(null , "a", true)  &lt; 0

1097    * StringUtils.compare(null , "a", false) &gt; 0

1098    * StringUtils.compare("a", null, true)   &gt; 0

1099    * StringUtils.compare("a", null, false)  &lt; 0

1100    * StringUtils.compare("abc", "abc", *)   = 0

1101    * StringUtils.compare("a", "b", *)       &lt; 0

1102    * StringUtils.compare("b", "a", *)       &gt; 0

1103    * StringUtils.compare("a", "B", *)       &gt; 0

1104    * StringUtils.compare("ab", "abc", *)    &lt; 0

1105    * </pre>

1106    *

1107    * @see String#compareTo(String)

1108    * @param str1  the String tocompare from

1109    * @param str2  the String tocompare to

1110    * @param nullIsLess  whetherconsider {@code null} value less than non-{@code null} value

1111    * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectivelyless, equal ou greater than {@code str2}

1112    * @since 3.5

1113    */

1114   public static int compare(final String str1, final String str2, finalboolean nullIsLess) {

1115       if (str1 == str2) {

1116            return 0;

1117       }

1118       if (str1 == null) {

1119            return nullIsLess ? -1 : 1;

1120       }

1121       if (str2 == null) {

1122            return nullIsLess ? 1 : - 1;

1123       }

1124       return str1.compareTo(str2);

1125   }

1126

1127   /**

1128    * <p>Compare two Strings lexicographically, ignoring casedifferences,

1129    * as per {@link String#compareToIgnoreCase(String)}, returning:</p>

1130    * <ul>

1131    *  <li>{@code int = 0}, if{@code str1} is equal to {@code str2} (or both {@code null})</li>

1132    *  <li>{@code int < 0},if {@code str1} is less than {@code str2}</li>

1133    *  <li>{@code int > 0},if {@code str1} is greater than {@code str2}</li>

1134    * </ul>

1135    *

1136    * <p>This is a {@code null} safe version of :</p>

1137    *<blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>

1138    *

1139    * <p>{@code null} value is considered less than non-{@code null}value.

1140    * Two {@code null} references areconsidered equal.

1141    * Comparison is case insensitive.</p>

1142    *

1143    * <pre>

1144    * StringUtils.compareIgnoreCase(null, null)   = 0

1145    * StringUtils.compareIgnoreCase(null , "a")   &lt; 0

1146    * StringUtils.compareIgnoreCase("a", null)    &gt; 0

1147    * StringUtils.compareIgnoreCase("abc", "abc") = 0

1148    * StringUtils.compareIgnoreCase("abc", "ABC") = 0

1149    * StringUtils.compareIgnoreCase("a", "b")     &lt; 0

1150    * StringUtils.compareIgnoreCase("b", "a")     &gt; 0

1151    * StringUtils.compareIgnoreCase("a", "B")     &lt; 0

1152    * StringUtils.compareIgnoreCase("A", "b")     &lt; 0

1153    * StringUtils.compareIgnoreCase("ab", "ABC")  &lt; 0

1154    * </pre>

1155    *

1156    * @see #compareIgnoreCase(String, String, boolean)

1157    * @see String#compareToIgnoreCase(String)

1158    * @param str1  the String tocompare from

1159    * @param str2  the String tocompare to

1160    * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectivelyless, equal ou greater than {@code str2},

1161    *          ignoring casedifferences.

1162    * @since 3.5

1163    */

1164   public static int compareIgnoreCase(final String str1, final Stringstr2) {

1165       return compareIgnoreCase(str1, str2, true);

1166   }

1167

1168   /**

1169    * <p>Compare two Strings lexicographically, ignoring casedifferences,

1170    * as per {@link String#compareToIgnoreCase(String)}, returning:</p>

1171    * <ul>

1172    *  <li>{@code int = 0}, if{@code str1} is equal to {@code str2} (or both {@code null})</li>

1173    *  <li>{@code int < 0},if {@code str1} is less than {@code str2}</li>

1174    *  <li>{@code int > 0},if {@code str1} is greater than {@code str2}</li>

1175    * </ul>

1176    *

1177    * <p>This is a {@code null} safe version of :</p>

1178    *<blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>

1179    *

1180    * <p>{@code null} inputs are handled according to the {@codenullIsLess} parameter.

1181    * Two {@code null} references are considered equal.

1182    * Comparison is case insensitive.</p>

1183    *

1184    * <pre>

1185    * StringUtils.compareIgnoreCase(null, null, *)     = 0

1186    * StringUtils.compareIgnoreCase(null , "a", true)  &lt; 0

1187    * StringUtils.compareIgnoreCase(null , "a", false) &gt; 0

1188    * StringUtils.compareIgnoreCase("a", null, true)   &gt; 0

1189    * StringUtils.compareIgnoreCase("a", null, false)  &lt; 0

1190    * StringUtils.compareIgnoreCase("abc", "abc",*)   = 0

1191    * StringUtils.compareIgnoreCase("abc", "ABC",*)   = 0

1192    * StringUtils.compareIgnoreCase("a", "b", *)       &lt; 0

1193    * StringUtils.compareIgnoreCase("b", "a", *)       &gt; 0

1194    * StringUtils.compareIgnoreCase("a", "B", *)       &lt; 0

1195    * StringUtils.compareIgnoreCase("A", "b", *)       &lt; 0

1196    * StringUtils.compareIgnoreCase("ab", "abc", *)    &lt; 0

1197    * </pre>

1198    *

1199    * @see String#compareToIgnoreCase(String)

1200    * @param str1  the String tocompare from

1201    * @param str2  the String tocompare to

1202    * @param nullIsLess  whetherconsider {@code null} value less than non-{@code null} value

1203    * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectivelyless, equal ou greater than {@code str2},

1204    *          ignoring casedifferences.

1205    * @since 3.5

1206    */

1207   public static int compareIgnoreCase(final String str1, final Stringstr2, final boolean nullIsLess) {

1208       if (str1 == str2) {

1209            return 0;

1210       }

1211       if (str1 == null) {

1212            return nullIsLess ? -1 : 1;

1213       }

1214       if (str2 == null) {

1215            return nullIsLess ? 1 : - 1;

1216       }

1217       return str1.compareToIgnoreCase(str2);

1218   }

1219

1220   /**

1221    * <p>Compares given <code>string</code> to aCharSequences vararg of <code>searchStrings</code>,

1222    * returning {@code true} if the <code>string</code> is equalto any of the <code>searchStrings</code>.</p>

1223    *

1224    * <pre>

1225    * StringUtils.equalsAny(null, (CharSequence[]) null) = false

1226    * StringUtils.equalsAny(null, null, null)    = true

1227    * StringUtils.equalsAny(null, "abc", "def")  = false

1228    * StringUtils.equalsAny("abc", null, "def")  = false

1229    * StringUtils.equalsAny("abc", "abc","def") = true

1230    * StringUtils.equalsAny("abc", "ABC","DEF") = false

1231    * </pre>

1232    *

1233    * @param string to compare, may be {@code null}.

1234    * @param searchStrings a vararg of strings, may be {@code null}.

1235    * @return {@code true} if the string is equal (case-sensitive) to anyother element of <code>searchStrings</code>;

1236    * {@code false} if <code>searchStrings</code> is null orcontains no matches.

1237    * @since 3.5

1238    */

1239   public static boolean equalsAny(final CharSequence string, finalCharSequence... searchStrings) {

1240       if (ArrayUtils.isNotEmpty(searchStrings)) {

1241            for (final CharSequence next :searchStrings) {

1242                if (equals(string, next)) {

1243                    return true;

1244                }

1245            }

1246       }

1247       return false;

1248   }

1249

1250

1251   /**

1252    * <p>Compares given <code>string</code> to aCharSequences vararg of <code>searchStrings</code>,

1253    * returning {@code true} if the <code>string</code> is equalto any of the <code>searchStrings</code>, ignoring case.</p>

1254    *

1255    * <pre>

1256    * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false

1257    * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true

1258    * StringUtils.equalsAnyIgnoreCase(null, "abc","def")  = false

1259    * StringUtils.equalsAnyIgnoreCase("abc", null,"def")  = false

1260    * StringUtils.equalsAnyIgnoreCase("abc", "abc","def") = true

1261    * StringUtils.equalsAnyIgnoreCase("abc", "ABC","DEF") = true

1262    * </pre>

1263    *

1264    * @param string to compare, may be {@code null}.

1265    * @param searchStrings a vararg of strings, may be {@code null}.

1266    * @return {@code true} if the string is equal (case-insensitive) to anyother element of <code>searchStrings</code>;

1267    * {@code false} if <code>searchStrings</code> is null orcontains no matches.

1268    * @since 3.5

1269    */

1270   public static boolean equalsAnyIgnoreCase(final CharSequence string,final CharSequence...searchStrings) {

1271       if (ArrayUtils.isNotEmpty(searchStrings)) {

1272            for (final CharSequence next :searchStrings) {

1273                if (equalsIgnoreCase(string,next)) {

1274                    return true;

1275                }

1276            }

1277        }

1278       return false;

1279   }

1280

1281   // IndexOf

1282   //-----------------------------------------------------------------------

1283   /**

1284    * Returns the index within <code>seq</code> of the firstoccurrence of

1285    * the specified character. If a character with value

1286    * <code>searchChar</code> occurs in the character sequencerepresented by

1287    * <code>seq</code> <code>CharSequence</code>object, then the index (in Unicode

1288    * code units) of the first such occurrence is returned. For

1289    * values of <code>searchChar</code> in the range from 0 to0xFFFF

1290    * (inclusive), this is the smallest value <i>k</i> suchthat:

1291    * <blockquote><pre>

1292    * this.charAt(<i>k</i>) == searchChar

1293    * </pre></blockquote>

1294    * is true. For other values of <code>searchChar</code>, itis the

1295    * smallest value <i>k</i> such that:

1296    * <blockquote><pre>

1297    * this.codePointAt(<i>k</i>) == searchChar

1298    * </pre></blockquote>

1299    * is true. In either case, if no such character occurs in<code>seq</code>,

1300    * then {@code INDEX_NOT_FOUND (-1)} is returned.

1301    *

1302    * <p>Furthermore, a {@code null} or empty ("")CharSequence will

1303    * return {@code INDEX_NOT_FOUND (-1)}.</p>

1304    *

1305    * <pre>

1306    * StringUtils.indexOf(null, *)        = -1

1307    * StringUtils.indexOf("", *)           = -1

1308    * StringUtils.indexOf("aabaabaa", 'a') = 0

1309    * StringUtils.indexOf("aabaabaa", 'b') = 2

1310    * </pre>

1311    *

1312    * @param seq  the CharSequence tocheck, may be null

1313    * @param searchChar  the characterto find

1314    * @return the first index of the search character,

1315    *  -1 if no match or {@code null}string input

1316    * @since 2.0

1317    * @since 3.0 Changed signature from indexOf(String, int) toindexOf(CharSequence, int)

1318    * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like<code>String</code>

1319    */

1320   public static int indexOf(final CharSequence seq, final int searchChar){

1321       if (isEmpty(seq)) {

1322            return INDEX_NOT_FOUND;

1323       }

1324       return CharSequenceUtils.indexOf(seq, searchChar, 0);

1325   }

1326

1327   /**

1328    *

1329    * Returns the index within <code>seq</code> of the firstoccurrence of the

1330    * specified character, starting the search at the specified index.

1331    * <p>

1332    * If a character with value <code>searchChar</code> occursin the

1333    * character sequence represented by the <code>seq</code><code>CharSequence</code>

1334    * object at an index no smaller than <code>startPos</code>,then

1335    * the index of the first such occurrence is returned. For values

1336    * of <code>searchChar</code> in the range from 0 to 0xFFFF(inclusive),

1337    * this is the smallest value <i>k</i> such that:

1338    * <blockquote><pre>

1339    * (this.charAt(<i>k</i>) == searchChar) &amp;&amp;(<i>k</i> &gt;= startPos)

1340    * </pre></blockquote>

1341    * is true. For other values of <code>searchChar</code>, itis the

1342    * smallest value <i>k</i> such that:

1343    * <blockquote><pre>

1344    * (this.codePointAt(<i>k</i>) == searchChar) &amp;&amp;(<i>k</i> &gt;= startPos)

1345    * </pre></blockquote>

1346    * is true. In either case, if no such character occurs in<code>seq</code>

1347    * at or after position <code>startPos</code>, then

1348    * <code>-1</code> is returned.

1349     *

1350    * <p>

1351    * There is no restriction on the value of<code>startPos</code>. If it

1352    * is negative, it has the same effect as if it were zero: this entire

1353    * string may be searched. If it is greater than the length of this

1354    * string, it has the same effect as if it were equal to the length of

1355    * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a

1356    * {@code null} or empty ("") CharSequence will

1357    * return {@code (INDEX_NOT_FOUND) -1}.

1358    *

1359    * <p>All indices are specified in <code>char</code>values

1360    * (Unicode code units).

1361    *

1362    * <pre>

1363    * StringUtils.indexOf(null, *, *)          = -1

1364    * StringUtils.indexOf("", *, *)            = -1

1365    * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2

1366    * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5

1367    * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1

1368    * StringUtils.indexOf("aabaabaa", 'b', -1) = 2

1369    * </pre>

1370    *

1371    * @param seq  the CharSequence tocheck, may be null

1372    * @param searchChar  the characterto find

1373    * @param startPos  the startposition, negative treated as zero

1374    * @return the first index of the search character (always &ge;startPos),

1375    *  -1 if no match or {@code null}string input

1376    * @since 2.0

1377    * @since 3.0 Changed signature from indexOf(String, int, int) toindexOf(CharSequence, int, int)

1378    * @since 3.6 Updated {@linkCharSequenceUtils} call to behave more like <code>String</code>

1379    */

1380   public static int indexOf(final CharSequence seq, final int searchChar,final int startPos) {

1381       if (isEmpty(seq)) {

1382            return INDEX_NOT_FOUND;

1383       }

1384       return CharSequenceUtils.indexOf(seq, searchChar, startPos);

1385   }

1386

1387   /**

1388    * <p>Finds the first index within a CharSequence, handling {@codenull}.

1389    * This method uses {@link String#indexOf(String, int)} ifpossible.</p>

1390    *

1391    * <p>A {@code null} CharSequence will return {@code -1}.</p>

1392    *

1393    * <pre>

1394    * StringUtils.indexOf(null, *)         = -1

1395    * StringUtils.indexOf(*, null)         = -1

1396    * StringUtils.indexOf("", "")           = 0

1397    * StringUtils.indexOf("", *)            = -1 (except when * = "")

1398    * StringUtils.indexOf("aabaabaa", "a")  = 0

1399    * StringUtils.indexOf("aabaabaa", "b")  = 2

1400    * StringUtils.indexOf("aabaabaa", "ab") = 1

1401    * StringUtils.indexOf("aabaabaa", "")   = 0

1402    * </pre>

1403    *

1404    * @param seq  the CharSequence tocheck, may be null

1405    * @param searchSeq  theCharSequence to find, may be null

1406    * @return the first index of the search CharSequence,

1407    *  -1 if no match or {@code null}string input

1408    * @since 2.0

1409    * @since 3.0 Changed signature from indexOf(String, String) toindexOf(CharSequence, CharSequence)

1410    */

1411   public static int indexOf(final CharSequence seq, final CharSequencesearchSeq) {

1412       if (seq == null || searchSeq == null) {

1413            return INDEX_NOT_FOUND;

1414       }

1415       return CharSequenceUtils.indexOf(seq, searchSeq, 0);

1416   }

1417

1418   /**

1419    * <p>Finds the first index within a CharSequence, handling {@codenull}.

1420    * This method uses {@link String#indexOf(String, int)} ifpossible.</p>

1421    *

1422    * <p>A {@code null} CharSequence will return {@code -1}.

1423    * A negative start position is treated as zero.

1424    * An empty ("") search CharSequence always matches.

1425     * A start position greater than the stringlength only matches

1426    * an empty search CharSequence.</p>

1427    *

1428    * <pre>

1429    * StringUtils.indexOf(null, *, *)          = -1

1430    * StringUtils.indexOf(*, null, *)          = -1

1431    * StringUtils.indexOf("", "", 0)           = 0

1432    * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")

1433    * StringUtils.indexOf("aabaabaa", "a", 0)  = 0

1434    * StringUtils.indexOf("aabaabaa", "b", 0)  = 2

1435    * StringUtils.indexOf("aabaabaa", "ab", 0) = 1

1436    * StringUtils.indexOf("aabaabaa", "b", 3)  = 5

1437    * StringUtils.indexOf("aabaabaa", "b", 9)  = -1

1438    * StringUtils.indexOf("aabaabaa", "b", -1) = 2

1439    * StringUtils.indexOf("aabaabaa", "", 2)   = 2

1440    * StringUtils.indexOf("abc", "", 9)        = 3

1441    * </pre>

1442    *

1443    * @param seq  the CharSequence tocheck, may be null

1444    * @param searchSeq  theCharSequence to find, may be null

1445    * @param startPos  the startposition, negative treated as zero

1446    * @return the first index of the search CharSequence (always &ge;startPos),

1447    *  -1 if no match or {@code null}string input

1448    * @since 2.0

1449    * @since 3.0 Changed signature from indexOf(String, String, int) toindexOf(CharSequence, CharSequence, int)

1450    */

1451   public static int indexOf(final CharSequence seq, final CharSequencesearchSeq, final int startPos) {

1452       if (seq == null || searchSeq == null) {

1453            return INDEX_NOT_FOUND;

1454       }

1455       return CharSequenceUtils.indexOf(seq, searchSeq, startPos);

1456   }

1457

1458   /**

1459    * <p>Finds the n-th index within a CharSequence, handling {@codenull}.

1460    * This method uses {@link String#indexOf(String)} if possible.</p>

1461    * <p><b>Note:</b> The code starts looking for a matchat the start of the target,

1462    * incrementing the starting index by one after each successful match

1463    * (unless {@code searchStr} is an empty string in which case theposition

1464    * is never incremented and {@code 0} is returned immediately).

1465    * This means that matches may overlap.</p>

1466    * <p>A {@code null} CharSequence will return {@code -1}.</p>

1467    *

1468    * <pre>

1469    * StringUtils.ordinalIndexOf(null, *, *)          = -1

1470    * StringUtils.ordinalIndexOf(*, null, *)          = -1

1471    * StringUtils.ordinalIndexOf("", "", *)           = 0

1472    * StringUtils.ordinalIndexOf("aabaabaa", "a",1)  = 0

1473    * StringUtils.ordinalIndexOf("aabaabaa", "a",2)  = 1

1474    * StringUtils.ordinalIndexOf("aabaabaa", "b",1)  = 2

1475    * StringUtils.ordinalIndexOf("aabaabaa", "b",2)  = 5

1476    * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) =1

1477    * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) =4

1478    * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0

1479    * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0

1480    * </pre>

1481    *

1482    * <p>Matches may overlap:</p>

1483    * <pre>

1484    * StringUtils.ordinalIndexOf("ababab","aba", 1)   = 0

1485    * StringUtils.ordinalIndexOf("ababab","aba", 2)   = 2

1486    * StringUtils.ordinalIndexOf("ababab","aba", 3)   = -1

1487    *

1488    * StringUtils.ordinalIndexOf("abababab", "abab", 1)= 0

1489    * StringUtils.ordinalIndexOf("abababab", "abab", 2)= 2

1490    * StringUtils.ordinalIndexOf("abababab", "abab", 3)= 4

1491    * StringUtils.ordinalIndexOf("abababab", "abab", 4)= -1

1492    * </pre>

1493    *

1494    * <p>Note that 'head(CharSequence str, int n)' may be implementedas: </p>

1495    *

1496    * <pre>

1497    *   str.substring(0, lastOrdinalIndexOf(str,"\n", n))

1498    * </pre>

1499    *

1500    * @param str  the CharSequence tocheck, may be null

1501    * @param searchStr  theCharSequence to find, may be null

1502    * @param ordinal  the n-th {@codesearchStr} to find

1503    * @return the n-th index of the search CharSequence,

1504    *  {@code -1} ({@codeINDEX_NOT_FOUND}) if no match or {@code null} string input

1505    * @since 2.1

1506    * @since 3.0 Changed signature from ordinalIndexOf(String, String, int)to ordinalIndexOf(CharSequence, CharSequence, int)

1507    */

1508   public static int ordinalIndexOf(final CharSequence str, finalCharSequence searchStr, final int ordinal) {

1509       return ordinalIndexOf(str, searchStr, ordinal, false);

1510   }

1511

1512   /**

1513    * <p>Finds the n-th index within a String, handling {@code null}.

1514    * This method uses {@link String#indexOf(String)} if possible.</p>

1515    * <p>Note that matches may overlap<p>

1516    *

1517    * <p>A {@code null} CharSequence will return {@code -1}.</p>

1518    *

1519    * @param str  the CharSequence tocheck, may be null

1520    * @param searchStr  theCharSequence to find, may be null

1521    * @param ordinal  the n-th {@codesearchStr} to find, overlapping matches are allowed.

1522    * @param lastIndex true if lastOrdinalIndexOf() otherwise false ifordinalIndexOf()

1523    * @return the n-th index of the search CharSequence,

1524    *  {@code -1} ({@codeINDEX_NOT_FOUND}) if no match or {@code null} string input

1525    */

1526   // Shared code between ordinalIndexOf(String,String,int) andlastOrdinalIndexOf(String,String,int)

1527   private static int ordinalIndexOf(final CharSequence str, finalCharSequence searchStr, final int ordinal, final boolean lastIndex) {

1528       if (str == null || searchStr == null || ordinal <= 0) {

1529            return INDEX_NOT_FOUND;

1530       }

1531       if (searchStr.length() == 0) {

1532            return lastIndex ? str.length() :0;

1533       }

1534       int found = 0;

1535       // set the initial index beyond the end of the string

1536       // this is to allow for the initial index decrement/increment

1537       int index = lastIndex ? str.length() : INDEX_NOT_FOUND;

1538       do {

1539            if (lastIndex) {

1540                index =CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwardsthru string

1541            } else {

1542                index = CharSequenceUtils.indexOf(str,searchStr, index + 1); // step forwards through string

1543            }

1544            if (index < 0) {

1545                return index;

1546            }

1547            found++;

1548       } while (found < ordinal);

1549       return index;

1550   }

1551

1552   /**

1553    * <p>Case in-sensitive find of the first index within aCharSequence.</p>

1554    *

1555    * <p>A {@code null} CharSequence will return {@code -1}.

1556    * A negative start position is treated as zero.

1557    * An empty ("") search CharSequence always matches.

1558    * A start position greater than the string length only matches

1559    * an empty search CharSequence.</p>

1560    *

1561    * <pre>

1562    * StringUtils.indexOfIgnoreCase(null, *)          = -1

1563    * StringUtils.indexOfIgnoreCase(*, null)          = -1

1564    * StringUtils.indexOfIgnoreCase("", "")           = 0

1565    * StringUtils.indexOfIgnoreCase("aabaabaa","a")  = 0

1566    * StringUtils.indexOfIgnoreCase("aabaabaa","b")  = 2

1567    * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") =1

1568    * </pre>

1569    *

1570    * @param str  the CharSequence tocheck, may be null

1571    * @param searchStr  the CharSequenceto find, may be null

1572    * @return the first index of the search CharSequence,

1573    *  -1 if no match or {@code null}string input

1574    * @since 2.5

1575    * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) toindexOfIgnoreCase(CharSequence, CharSequence)

1576    */

1577   public static int indexOfIgnoreCase(final CharSequence str, finalCharSequence searchStr) {

1578       return indexOfIgnoreCase(str, searchStr, 0);

1579   }

1580

1581   /**

1582    * <p>Case in-sensitive find of the first index within aCharSequence

1583    * from the specified position.</p>

1584    *

1585    * <p>A {@code null} CharSequence will return {@code -1}.

1586    * A negative start position is treated as zero.

1587    * An empty ("") search CharSequence always matches.

1588    * A start position greater than the string length only matches

1589    * an empty search CharSequence.</p>

1590    *

1591    * <pre>

1592    * StringUtils.indexOfIgnoreCase(null, *, *)          = -1

1593    * StringUtils.indexOfIgnoreCase(*, null, *)          = -1

1594    * StringUtils.indexOfIgnoreCase("", "", 0)           = 0

1595    * StringUtils.indexOfIgnoreCase("aabaabaa", "A",0)  = 0

1596    * StringUtils.indexOfIgnoreCase("aabaabaa", "B",0)  = 2

1597    * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0)= 1

1598    * StringUtils.indexOfIgnoreCase("aabaabaa", "B",3)  = 5

1599    * StringUtils.indexOfIgnoreCase("aabaabaa", "B",9)  = -1

1600    * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1)= 2

1601    * StringUtils.indexOfIgnoreCase("aabaabaa", "",2)   = 2

1602    * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1

1603    * </pre>

1604    *

1605    * @param str  the CharSequence tocheck, may be null

1606    * @param searchStr  theCharSequence to find, may be null

1607    * @param startPos  the startposition, negative treated as zero

1608    * @return the first index of the search CharSequence (always &ge;startPos),

1609    *  -1 if no match or {@code null}string input

1610    * @since 2.5

1611    * @since 3.0 Changed signature from indexOfIgnoreCase(String, String,int) to indexOfIgnoreCase(CharSequence, CharSequence, int)

1612    */

1613   public static int indexOfIgnoreCase(final CharSequence str, finalCharSequence searchStr, int startPos) {

1614       if (str == null || searchStr == null) {

1615            return INDEX_NOT_FOUND;

1616       }

1617       if (startPos < 0) {

1618            startPos = 0;

1619       }

1620       final int endLimit = str.length() - searchStr.length() + 1;

1621       if (startPos > endLimit) {

1622            return INDEX_NOT_FOUND;

1623       }

1624       if (searchStr.length() == 0) {

1625            return startPos;

1626       }

1627       for (int i = startPos; i < endLimit; i++) {

1628            if(CharSequenceUtils.regionMatches(str, true, i, searchStr, 0,searchStr.length())) {

1629                return i;

1630            }

1631        }

1632       return INDEX_NOT_FOUND;

1633   }

1634

1635   // LastIndexOf

1636   //-----------------------------------------------------------------------

1637   /**

1638    * Returns the index within <code>seq</code> of the lastoccurrence of

1639    * the specified character. For values of<code>searchChar</code> in the

1640    * range from 0 to 0xFFFF (inclusive), the index (in Unicode code

1641    * units) returned is the largest value <i>k</i> such that:

1642    * <blockquote><pre>

1643    * this.charAt(<i>k</i>) == searchChar

1644    * </pre></blockquote>

1645    * is true. For other values of <code>searchChar</code>, itis the

1646    * largest value <i>k</i> such that:

1647    * <blockquote><pre>

1648    * this.codePointAt(<i>k</i>) == searchChar

1649    * </pre></blockquote>

1650    * is true.  In either case, if nosuch character occurs in this

1651    * string, then <code>-1</code> is returned. Furthermore, a{@code null} or empty ("")

1652    * <code>CharSequence</code> will return {@code -1}. The

1653    * <code>seq</code> <code>CharSequence</code>object is searched backwards

1654    * starting at the last character.

1655    *

1656    * <pre>

1657    * StringUtils.lastIndexOf(null, *)         = -1

1658    * StringUtils.lastIndexOf("", *)           = -1

1659    * StringUtils.lastIndexOf("aabaabaa", 'a') = 7

1660    * StringUtils.lastIndexOf("aabaabaa", 'b') = 5

1661    * </pre>

1662    *

1663    * @param seq  the<code>CharSequence</code> to check, may be null

1664    * @param searchChar  the characterto find

1665    * @return the last index of the search character,

1666    *  -1 if no match or {@code null}string input

1667    * @since 2.0

1668    * @since 3.0 Changed signature from lastIndexOf(String, int) tolastIndexOf(CharSequence, int)

1669    * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like<code>String</code>

1670    */

1671   public static int lastIndexOf(final CharSequence seq, final intsearchChar) {

1672       if (isEmpty(seq)) {

1673            return INDEX_NOT_FOUND;

1674       }

1675       return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());

1676   }

1677

1678   /**

1679    * Returns the index within <code>seq</code> of the lastoccurrence of

1680    * the specified character, searching backward starting at the

1681    * specified index. For values of <code>searchChar</code> inthe range

1682    * from 0 to 0xFFFF (inclusive), the index returned is the largest

1683    * value <i>k</i> such that:

1684    * <blockquote><pre>

1685    * (this.charAt(<i>k</i>) == searchChar) &amp;&amp;(<i>k</i> &lt;= startPos)

1686    * </pre></blockquote>

1687    * is true. For other values of <code>searchChar</code>, itis the

1688    * largest value <i>k</i> such that:

1689    * <blockquote><pre>

1690    * (this.codePointAt(<i>k</i>) == searchChar)&amp;&amp; (<i>k</i> &lt;= startPos)

1691    * </pre></blockquote>

1692    * is true. In either case, if no such character occurs in<code>seq</code>

1693     * at or before position<code>startPos</code>, then

1694    * <code>-1</code> is returned. Furthermore, a {@code null}or empty ("")

1695    * <code>CharSequence</code> will return {@code -1}. A startposition greater

1696    * than the string length searches the whole string.

1697    * The search starts at the <code>startPos</code> and worksbackwards;

1698    * matches starting after the start position are ignored.

1699    *

1700    * <p>All indices are specified in <code>char</code>values

1701    * (Unicode code units).

1702    *

1703    * <pre>

1704    * StringUtils.lastIndexOf(null, *, *)          = -1

1705    * StringUtils.lastIndexOf("", *,  *)          = -1

1706    * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5

1707    * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2

1708    * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1

1709    * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5

1710    * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1

1711    * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0

1712    * </pre>

1713    *

1714    * @param seq  the CharSequence tocheck, may be null

1715    * @param searchChar  the characterto find

1716    * @param startPos  the startposition

1717    * @return the last index of the search character (always &le;startPos),

1718    *  -1 if no match or {@code null}string input

1719    * @since 2.0

1720    * @since 3.0 Changed signature from lastIndexOf(String, int, int) tolastIndexOf(CharSequence, int, int)

1721    */

1722   public static int lastIndexOf(final CharSequence seq, final intsearchChar, final int startPos) {

1723       if (isEmpty(seq)) {

1724            return INDEX_NOT_FOUND;

1725       }

1726       return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);

1727   }

1728

1729   /**

1730    * <p>Finds the last index within a CharSequence, handling {@codenull}.

1731    * This method uses {@link String#lastIndexOf(String)} ifpossible.</p>

1732    *

1733    * <p>A {@code null} CharSequence will return {@code -1}.</p>

1734    *

1735    * <pre>

1736    * StringUtils.lastIndexOf(null, *)          = -1

1737    * StringUtils.lastIndexOf(*, null)          = -1

1738    * StringUtils.lastIndexOf("", "")           = 0

1739    * StringUtils.lastIndexOf("aabaabaa", "a")  = 7

1740    * StringUtils.lastIndexOf("aabaabaa", "b")  = 5

1741    * StringUtils.lastIndexOf("aabaabaa", "ab") = 4

1742    * StringUtils.lastIndexOf("aabaabaa", "")   = 8

1743    * </pre>

1744    *

1745    * @param seq  the CharSequence tocheck, may be null

1746    * @param searchSeq  theCharSequence to find, may be null

1747    * @return the last index of the search String,

1748    *  -1 if no match or {@code null}string input

1749    * @since 2.0

1750    * @since 3.0 Changed signature from lastIndexOf(String, String) tolastIndexOf(CharSequence, CharSequence)

1751    */

1752   public static int lastIndexOf(final CharSequence seq, final CharSequencesearchSeq) {

1753       if (seq == null || searchSeq == null) {

1754            return INDEX_NOT_FOUND;

1755       }

1756       return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());

1757   }

1758

1759   /**

1760    * <p>Finds the n-th last index within a String, handling {@code null}.

1761    * This method uses {@link String#lastIndexOf(String)}.</p>

1762    *

1763    * <p>A {@code null} String will return {@code -1}.</p>

1764    *

1765    * <pre>

1766    * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1

1767    * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1

1768    * StringUtils.lastOrdinalIndexOf("", "", *)           = 0

1769    * StringUtils.lastOrdinalIndexOf("aabaabaa", "a",1)  = 7

1770    * StringUtils.lastOrdinalIndexOf("aabaabaa", "a",2)  = 6

1771    * StringUtils.lastOrdinalIndexOf("aabaabaa", "b",1)  = 5

1772    * StringUtils.lastOrdinalIndexOf("aabaabaa", "b",2)  = 2

1773    * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab",1) = 4

1774    * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab",2) = 1

1775    * StringUtils.lastOrdinalIndexOf("aabaabaa", "",1)   = 8

1776    * StringUtils.lastOrdinalIndexOf("aabaabaa", "",2)   = 8

1777    * </pre>

1778    *

1779    * <p>Note that 'tail(CharSequence str, int n)' may be implementedas: </p>

1780    *

1781    * <pre>

1782    *  str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)

1783    * </pre>

1784    *

1785    * @param str  the CharSequence tocheck, may be null

1786     * @param searchStr  the CharSequence to find, may be null

1787    * @param ordinal  the n-th last{@code searchStr} to find

1788    * @return the n-th last index of the search CharSequence,

1789    *  {@code -1} ({@codeINDEX_NOT_FOUND}) if no match or {@code null} string input

1790    * @since 2.5

1791    * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String,int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)

1792    */

1793   public static int lastOrdinalIndexOf(final CharSequence str, finalCharSequence searchStr, final int ordinal) {

1794       return ordinalIndexOf(str, searchStr, ordinal, true);

1795   }

1796

1797   /**

1798    * <p>Finds the last index within a CharSequence, handling {@codenull}.

1799    * This method uses {@link String#lastIndexOf(String, int)} ifpossible.</p>

1800    *

1801    * <p>A {@code null} CharSequence will return {@code -1}.

1802    * A negative start position returns {@code -1}.

1803    * An empty ("") search CharSequence always matches unless thestart position is negative.

1804    * A start position greater than the string length searches the wholestring.

1805    * The search starts at the startPos and works backwards; matchesstarting after the start

1806    * position are ignored.

1807    * </p>

1808    *

1809    * <pre>

1810    * StringUtils.lastIndexOf(null, *, *)          = -1

1811    * StringUtils.lastIndexOf(*, null, *)          = -1

1812    * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7

1813    * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5

1814    * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4

1815    * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5

1816    * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1

1817    * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0

1818    * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1

1819    * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1

1820    * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2

1821    * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = -1

1822    * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2

1823    * </pre>

1824    *

1825    * @param seq  the CharSequence tocheck, may be null

1826    * @param searchSeq  theCharSequence to find, may be null

1827    * @param startPos  the startposition, negative treated as zero

1828    * @return the last index of the search CharSequence (always &le;startPos),

1829    *  -1 if no match or {@code null}string input

1830    * @since 2.0

1831    * @since 3.0 Changed signature from lastIndexOf(String, String, int) tolastIndexOf(CharSequence, CharSequence, int)

1832    */

1833   public static int lastIndexOf(final CharSequence seq, final CharSequencesearchSeq, final int startPos) {

1834       if (seq == null || searchSeq == null) {

1835            return INDEX_NOT_FOUND;

1836       }

1837       return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);

1838   }

1839

1840   /**

1841    * <p>Case in-sensitive find of the last index within aCharSequence.</p>

1842    *

1843    * <p>A {@code null} CharSequence will return {@code -1}.

1844    * A negative start position returns {@code -1}.

1845    * An empty ("") search CharSequence always matches unless thestart position is negative.

1846    * A start position greater than the string length searches the wholestring.</p>

1847    *

1848    * <pre>

1849    * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1

1850    * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1

1851    * StringUtils.lastIndexOfIgnoreCase("aabaabaa","A")  = 7

1852    * StringUtils.lastIndexOfIgnoreCase("aabaabaa","B")  = 5

1853    * StringUtils.lastIndexOfIgnoreCase("aabaabaa","AB") = 4

1854    * </pre>

1855    *

1856    * @param str  the CharSequence tocheck, may be null

1857    * @param searchStr  theCharSequence to find, may be null

1858    * @return the first index of the search CharSequence,

1859    *  -1 if no match or {@code null}string input

1860    * @since 2.5

1861    * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String,String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)

1862    */

1863   public static int lastIndexOfIgnoreCase(final CharSequence str, finalCharSequence searchStr) {

1864       if (str == null || searchStr == null) {

1865            return INDEX_NOT_FOUND;

1866       }

1867       return lastIndexOfIgnoreCase(str, searchStr, str.length());

1868   }

1869

1870   /**

1871    * <p>Case in-sensitive find of the last index within aCharSequence

1872    * from the specified position.</p>

1873    *

1874    * <p>A {@code null} CharSequence will return {@code -1}.

1875    * A negative start position returns {@code -1}.

1876    * An empty ("") search CharSequence always matches unless thestart position is negative.

1877    * A start position greater than the string length searches the wholestring.

1878    * The search starts at the startPos and works backwards; matchesstarting after the start

1879    * position are ignored.

1880    * </p>

1881    *

1882    * <pre>

1883    * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1

1884    * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1

1885    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A",8)  = 7

1886    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B",8)  = 5

1887    * StringUtils.lastIndexOfIgnoreCase("aabaabaa","AB", 8) = 4

1888    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B",9)  = 5

1889    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B",-1) = -1

1890    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A",0)  = 0

1891    * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B",0)  = -1

1892    * </pre>

1893    *

1894    * @param str  the CharSequence tocheck, may be null

1895    * @param searchStr  theCharSequence to find, may be null

1896    * @param startPos  the startposition

1897    * @return the last index of the search CharSequence (always &le;startPos),

1898    *  -1 if no match or {@code null}input

1899    * @since 2.5

1900    * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String,String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)

1901    */

1902   public static int lastIndexOfIgnoreCase(final CharSequence str, finalCharSequence searchStr, int startPos) {

1903       if (str == null || searchStr == null) {

1904           return INDEX_NOT_FOUND;

1905       }

1906       if (startPos > str.length() - searchStr.length()) {

1907            startPos = str.length() -searchStr.length();

1908       }

1909       if (startPos < 0) {

1910            return INDEX_NOT_FOUND;

1911       }

1912       if (searchStr.length() == 0) {

1913            return startPos;

1914       }

1915

1916       for (int i = startPos; i >= 0; i--) {

1917            if(CharSequenceUtils.regionMatches(str, true, i, searchStr, 0,searchStr.length())) {

1918                return i;

1919            }

1920       }

1921       return INDEX_NOT_FOUND;

1922   }

1923

1924   // Contains

1925   //-----------------------------------------------------------------------

1926   /**

1927    * <p>Checks if CharSequence contains a search character, handling{@code null}.

1928    * This method uses {@link String#indexOf(int)} if possible.</p>

1929    *

1930    * <p>A {@code null} or empty ("") CharSequence willreturn {@code false}.</p>

1931    *

1932    * <pre>

1933    * StringUtils.contains(null, *)   = false

1934    * StringUtils.contains("", *)      = false

1935    * StringUtils.contains("abc", 'a') = true

1936    * StringUtils.contains("abc", 'z') = false

1937    * </pre>

1938    *

1939    * @param seq  the CharSequence tocheck, may be null

1940    * @param searchChar  the characterto find

1941    * @return true if the CharSequence contains the search character,

1942    *  false if not or {@code null}string input

1943    * @since 2.0

1944    * @since 3.0 Changed signature from contains(String, int) tocontains(CharSequence, int)

1945    */

1946   public static boolean contains(final CharSequence seq, final intsearchChar) {

1947       if (isEmpty(seq)) {

1948            return false;

1949       }

1950       return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;

1951   }

1952

1953    /**

1954    * <p>Checks if CharSequence contains a search CharSequence,handling {@code null}.

1955    * This method uses {@link String#indexOf(String)} if possible.</p>

1956    *

1957    * <p>A {@code null} CharSequence will return {@code false}.</p>

1958    *

1959    * <pre>

1960    * StringUtils.contains(null, *)    = false

1961    * StringUtils.contains(*, null)    = false

1962    * StringUtils.contains("", "")      = true

1963    * StringUtils.contains("abc", "")   = true

1964    * StringUtils.contains("abc", "a")  = true

1965    * StringUtils.contains("abc", "z")  = false

1966    * </pre>

1967    *

1968    * @param seq  the CharSequence tocheck, may be null

1969    * @param searchSeq  theCharSequence to find, may be null

1970    * @return true if the CharSequence contains the search CharSequence,

1971    *  false if not or {@code null}string input

1972    * @since 2.0

1973    * @since 3.0 Changed signature from contains(String, String) tocontains(CharSequence, CharSequence)

1974    */

1975   public static boolean contains(final CharSequence seq, finalCharSequence searchSeq) {

1976       if (seq == null || searchSeq == null) {

1977            return false;

1978       }

1979       return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;

1980   }

1981

1982   /**

1983    * <p>Checks if CharSequence contains a search CharSequenceirrespective of case,

1984    * handling {@code null}. Case-insensitivity is defined as by

1985    * {@link String#equalsIgnoreCase(String)}.

1986    *

1987    * <p>A {@code null} CharSequence will return {@codefalse}.</p>

1988    *

1989    * <pre>

1990    * StringUtils.containsIgnoreCase(null, *) = false

1991    * StringUtils.containsIgnoreCase(*, null) = false

1992    * StringUtils.containsIgnoreCase("", "") = true

1993    * StringUtils.containsIgnoreCase("abc", "") = true

1994    * StringUtils.containsIgnoreCase("abc", "a") = true

1995    * StringUtils.containsIgnoreCase("abc", "z") = false

1996    * StringUtils.containsIgnoreCase("abc", "A") = true

1997    * StringUtils.containsIgnoreCase("abc", "Z") = false

1998    * </pre>

1999    *

2000    * @param str  the CharSequence tocheck, may be null

2001    * @param searchStr  theCharSequence to find, may be null

2002    * @return true if the CharSequence contains the search CharSequenceirrespective of

2003    * case or false if not or {@code null} string input

2004    * @since 3.0 Changed signature from containsIgnoreCase(String, String)to containsIgnoreCase(CharSequence, CharSequence)

2005    */

2006   public static boolean containsIgnoreCase(final CharSequence str, finalCharSequence searchStr) {

2007       if (str == null || searchStr == null) {

2008            return false;

2009       }

2010       final int len = searchStr.length();

2011       final int max = str.length() - len;

2012       for (int i = 0; i <= max; i++) {

2013            if(CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {

2014                return true;

2015            }

2016       }

2017       return false;

2018   }

2019

2020   /**

2021    * <p>Check whether the given CharSequence contains any whitespacecharacters.</p>

2022    *

2023    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

2024    *

2025    * @param seq the CharSequence to check (may be {@code null})

2026    * @return {@code true} if the CharSequence is not empty and

2027    * contains at least 1 (breaking) whitespace character

2028    * @since 3.0

2029    */

2030   // From org.springframework.util.StringUtils, under Apache License 2.0

2031   public static boolean containsWhitespace(final CharSequence seq) {

2032       if (isEmpty(seq)) {

2033            return false;

2034       }

2035       final int strLen = seq.length();

2036       for (int i = 0; i < strLen; i++) {

2037            if(Character.isWhitespace(seq.charAt(i))) {

2038                return true;

2039            }

2040       }

2041       return false;

2042   }

2043

2044   // IndexOfAny chars

2045   //-----------------------------------------------------------------------

2046   /**

2047    * <p>Search a CharSequence to find the first index of any

2048    * character in the given set of characters.</p>

2049    *

2050    * <p>A {@code null} String will return {@code -1}.

2051    * A {@code null} or zero length search array will return {@code-1}.</p>

2052    *

2053    * <pre>

2054    * StringUtils.indexOfAny(null, *)                = -1

2055    * StringUtils.indexOfAny("", *)                  = -1

2056    * StringUtils.indexOfAny(*, null)                = -1

2057    * StringUtils.indexOfAny(*, [])                  = -1

2058    * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0

2059    * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3

2060    * StringUtils.indexOfAny("aba", ['z'])           = -1

2061    * </pre>

2062    *

2063    * @param cs  the CharSequence tocheck, may be null

2064    * @param searchChars  the chars tosearch for, may be null

2065    * @return the index of any of the chars, -1 if no match or null input

2066    * @since 2.0

2067    * @since 3.0 Changed signaturefrom indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)

2068    */

2069   public static int indexOfAny(final CharSequence cs, final char...searchChars) {

2070       if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {

2071            return INDEX_NOT_FOUND;

2072       }

2073       final int csLen = cs.length();

2074       final int csLast = csLen - 1;

2075       final int searchLen = searchChars.length;

2076       final int searchLast = searchLen - 1;

2077       for (int i = 0; i < csLen; i++) {

2078            final char ch = cs.charAt(i);

2079            for (int j = 0; j < searchLen;j++) {

2080                if (searchChars[j] == ch) {

2081                    if (i < csLast&& j < searchLast && Character.isHighSurrogate(ch)) {

2082                        // ch is asupplementary character

2083                        if (searchChars[j + 1]== cs.charAt(i + 1)) {

2084                            return i;

2085                        }

2086                   } else {

2087                        return i;

2088                    }

2089                }

2090            }

2091       }

2092       return INDEX_NOT_FOUND;

2093   }

2094

2095   /**

2096    * <p>Search a CharSequence to find the first index of any

2097    * character in the given set of characters.</p>

2098    *

2099    * <p>A {@code null} String will return {@code -1}.

2100    * A {@code null} search string will return {@code -1}.</p>

2101    *

2102    * <pre>

2103    * StringUtils.indexOfAny(null, *)            = -1

2104    * StringUtils.indexOfAny("", *)              = -1

2105    * StringUtils.indexOfAny(*, null)            = -1

2106    * StringUtils.indexOfAny(*, "")              = -1

2107    * StringUtils.indexOfAny("zzabyycdxx", "za") = 0

2108    * StringUtils.indexOfAny("zzabyycdxx", "by") = 3

2109    * StringUtils.indexOfAny("aba","z")          = -1

2110    * </pre>

2111    *

2112    * @param cs  the CharSequence tocheck, may be null

2113    * @param searchChars  the chars tosearch for, may be null

2114    * @return the index of any of the chars, -1 if no match or null input

2115    * @since 2.0

2116    * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence,String)

2117    */

2118   public static int indexOfAny(final CharSequence cs, final StringsearchChars) {

2119       if (isEmpty(cs) || isEmpty(searchChars)) {

2120            return INDEX_NOT_FOUND;

2121       }

2122       return indexOfAny(cs, searchChars.toCharArray());

2123   }

2124

2125   // ContainsAny

2126   //-----------------------------------------------------------------------

2127   /**

2128    * <p>Checks if the CharSequence contains any character in thegiven

2129    * set of characters.</p>

2130    *

2131    * <p>A {@code null} CharSequence will return {@code false}.

2132    * A {@code null} or zero length search array will return {@codefalse}.</p>

2133    *

2134    * <pre>

2135    * StringUtils.containsAny(null, *)                = false

2136    * StringUtils.containsAny("", *)                  = false

2137    * StringUtils.containsAny(*, null)                = false

2138    * StringUtils.containsAny(*, [])                  = false

2139    * StringUtils.containsAny("zzabyycdxx",['z','a']) = true

2140    * StringUtils.containsAny("zzabyycdxx",['b','y']) = true

2141    * StringUtils.containsAny("zzabyycdxx",['z','y']) = true

2142    * StringUtils.containsAny("aba", ['z'])           = false

2143    * </pre>

2144    *

2145    * @param cs  the CharSequence tocheck, may be null

2146    * @param searchChars  the chars tosearch for, may be null

2147    * @return the {@code true} if any of the chars are found,

2148    * {@code false} if no match or null input

2149    * @since 2.4

2150    * @since 3.0 Changed signature from containsAny(String, char[]) tocontainsAny(CharSequence, char...)

2151    */

2152   public static boolean containsAny(final CharSequence cs, final char...searchChars) {

2153       if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {

2154            return false;

2155       }

2156       final int csLength = cs.length();

2157       final int searchLength = searchChars.length;

2158       final int csLast = csLength - 1;

2159       final int searchLast = searchLength - 1;

2160       for (int i = 0; i < csLength; i++) {

2161            final char ch = cs.charAt(i);

2162            for (int j = 0; j <searchLength; j++) {

2163               if (searchChars[j] ==ch) {

2164                    if(Character.isHighSurrogate(ch)) {

2165                        if (j == searchLast) {

2166                            // missing lowsurrogate, fine, like String.indexOf(String)

2167                           return true;

2168                        }

2169                        if (i < csLast&& searchChars[j + 1] == cs.charAt(i + 1)) {

2170                            return true;

2171                        }

2172                    } else {

2173                        // ch is in the BasicMultilingual Plane

2174                        return true;

2175                    }

2176                }

2177            }

2178       }

2179       return false;

2180   }

2181

2182   /**

2183    * <p>

2184    * Checks if the CharSequence contains any character in the given set ofcharacters.

2185    * </p>

2186    *

2187    * <p>

2188    * A {@code null} CharSequence will return {@code false}. A {@code null}search CharSequence will return

2189     * {@code false}.

2190    * </p>

2191    *

2192    * <pre>

2193    * StringUtils.containsAny(null, *)               = false

2194    * StringUtils.containsAny("", *)                 = false

2195    * StringUtils.containsAny(*, null)               = false

2196    * StringUtils.containsAny(*, "")                 = false

2197    * StringUtils.containsAny("zzabyycdxx", "za")    = true

2198    * StringUtils.containsAny("zzabyycdxx", "by")    = true

2199    * StringUtils.containsAny("zzabyycdxx", "zy")    = true

2200    * StringUtils.containsAny("zzabyycdxx", "\tx")   = true

2201    * StringUtils.containsAny("zzabyycdxx", "$.#yF") =true

2202    * StringUtils.containsAny("aba","z")             = false

2203    * </pre>

2204    *

2205    * @param cs

2206    *            the CharSequence tocheck, may be null

2207    * @param searchChars

2208    *            the chars to searchfor, may be null

2209    * @return the {@code true} if any of the chars are found, {@code false}if no match or null input

2210    * @since 2.4

2211    * @since 3.0 Changed signature from containsAny(String, String) tocontainsAny(CharSequence, CharSequence)

2212    */

2213   public static boolean containsAny(final CharSequence cs, finalCharSequence searchChars) {

2214       if (searchChars == null) {

2215            return false;

2216       }

2217       return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));

2218   }

2219

2220   /**

2221    * <p>Checks if the CharSequence contains any of the CharSequencesin the given array.</p>

2222    *

2223    * <p>

2224    * A {@code null} {@code cs} CharSequence will return {@code false}. A{@code null} or zero

2225    * length search array will return {@code false}.

2226    * </p>

2227    *

2228    * <pre>

2229    * StringUtils.containsAny(null, *)            = false

2230    * StringUtils.containsAny("", *)              = false

2231    * StringUtils.containsAny(*, null)            = false

2232    * StringUtils.containsAny(*, [])              = false

2233    * StringUtils.containsAny("abcd", "ab", null) = true

2234    * StringUtils.containsAny("abcd", "ab","cd") = true

2235    * StringUtils.containsAny("abc", "d","abc")  = true

2236    * </pre>

2237    *

2238    *

2239    * @param cs The CharSequence to check, may be null

2240    * @param searchCharSequences The array of CharSequences to search for,may be null.

2241    * Individual CharSequences may be null as well.

2242    * @return {@code true} if any of the search CharSequences are found,{@code false} otherwise

2243    * @since 3.4

2244    */

2245   public static boolean containsAny(final CharSequence cs, finalCharSequence... searchCharSequences) {

2246       if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {

2247            return false;

2248       }

2249       for (final CharSequence searchCharSequence : searchCharSequences) {

2250            if (contains(cs,searchCharSequence)) {

2251                return true;

2252            }

2253       }

2254       return false;

2255   }

2256

2257   // IndexOfAnyBut chars

2258   //-----------------------------------------------------------------------

2259   /**

2260    * <p>Searches a CharSequence to find the first index of any

2261    * character not in the given set of characters.</p>

2262    *

2263    * <p>A {@code null} CharSequence will return {@code -1}.

2264    * A {@code null} or zero length search array will return {@code-1}.</p>

2265    *

2266    * <pre>

2267    * StringUtils.indexOfAnyBut(null, *)                              = -1

2268    * StringUtils.indexOfAnyBut("", *)                                = -1

2269    * StringUtils.indexOfAnyBut(*, null)                              = -1

2270    * StringUtils.indexOfAnyBut(*, [])                                = -1

2271    * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z','a'} ) = 3

2272    * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0

2273    * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'})        = -1

2274

2275    * </pre>

2276    *

2277    * @param cs  the CharSequence tocheck, may be null

2278    * @param searchChars  the chars tosearch for, may be null

2279    * @return the index of any of the chars, -1 if no match or null input

2280    * @since 2.0

2281    * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) toindexOfAnyBut(CharSequence, char...)

2282    */

2283   public static int indexOfAnyBut(final CharSequence cs, final char...searchChars) {

2284       if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {

2285            return INDEX_NOT_FOUND;

2286       }

2287       final int csLen = cs.length();

2288       final int csLast = csLen - 1;

2289       final int searchLen = searchChars.length;

2290       final int searchLast = searchLen - 1;

2291       outer:

2292       for (int i = 0; i < csLen; i++) {

2293            final char ch = cs.charAt(i);

2294            for (int j = 0; j < searchLen;j++) {

2295                if (searchChars[j] == ch) {

2296                    if (i < csLast&& j < searchLast && Character.isHighSurrogate(ch)) {

2297                        if (searchChars[j + 1]== cs.charAt(i + 1)) {

2298                            continue outer;

2299                        }

2300                    } else {

2301                        continue outer;

2302                    }

2303                }

2304            }

2305            return i;

2306       }

2307       return INDEX_NOT_FOUND;

2308   }

2309

2310   /**

2311    * <p>Search a CharSequence to find the first index of any

2312    * character not in the given set of characters.</p>

2313    *

2314    * <p>A {@code null} CharSequence will return {@code -1}.

2315    * A {@code null} or empty search string will return {@code-1}.</p>

2316    *

2317    * <pre>

2318    * StringUtils.indexOfAnyBut(null, *)            = -1

2319    * StringUtils.indexOfAnyBut("", *)              = -1

2320    * StringUtils.indexOfAnyBut(*, null)            = -1

2321    * StringUtils.indexOfAnyBut(*, "")              = -1

2322    * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3

2323    * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1

2324    * StringUtils.indexOfAnyBut("aba","ab")         = -1

2325    * </pre>

2326    *

2327    * @param seq  the CharSequence tocheck, may be null

2328    * @param searchChars  the chars tosearch for, may be null

2329    * @return the index of any of the chars, -1 if no match or null input

2330    * @since 2.0

2331    * @since 3.0 Changed signature from indexOfAnyBut(String, String) toindexOfAnyBut(CharSequence, CharSequence)

2332    */

2333   public static int indexOfAnyBut(final CharSequence seq, finalCharSequence searchChars) {

2334       if (isEmpty(seq) || isEmpty(searchChars)) {

2335            return INDEX_NOT_FOUND;

2336       }

2337       final int strLen = seq.length();

2338       for (int i = 0; i < strLen; i++) {

2339            final char ch = seq.charAt(i);

2340            final boolean chFound =CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;

2341            if (i + 1 < strLen &&Character.isHighSurrogate(ch)) {

2342                final char ch2 = seq.charAt(i +1);

2343                if (chFound &&CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {

2344                    return i;

2345                }

2346            } else {

2347                if (!chFound) {

2348                    return i;

2349                }

2350            }

2351       }

2352       return INDEX_NOT_FOUND;

2353   }

2354

2355   // ContainsOnly

2356   //-----------------------------------------------------------------------

2357   /**

2358    * <p>Checks if the CharSequence contains only certaincharacters.</p>

2359    *

2360    * <p>A {@code null} CharSequence will return {@code false}.

2361    * A {@code null} valid character array will return {@code false}.

2362    * An empty CharSequence (length()=0) always returns {@codetrue}.</p>

2363    *

2364    * <pre>

2365    * StringUtils.containsOnly(null, *)      = false

2366    * StringUtils.containsOnly(*, null)      = false

2367    * StringUtils.containsOnly("", *)         = true

2368    * StringUtils.containsOnly("ab", '')      = false

2369    * StringUtils.containsOnly("abab", 'abc') = true

2370    * StringUtils.containsOnly("ab1", 'abc')  = false

2371    * StringUtils.containsOnly("abz", 'abc')  = false

2372    * </pre>

2373    *

2374    * @param cs  the String to check,may be null

2375    * @param valid  an array of validchars, may be null

2376    * @return true if it only contains valid chars and is non-null

2377    * @since 3.0 Changed signature from containsOnly(String, char[]) tocontainsOnly(CharSequence, char...)

2378    */

2379   public static boolean containsOnly(final CharSequence cs, final char...valid) {

2380       // All these pre-checks are to maintain API with an older version

2381       if (valid == null || cs == null) {

2382            return false;

2383       }

2384       if (cs.length() == 0) {

2385            return true;

2386       }

2387       if (valid.length == 0) {

2388            return false;

2389       }

2390       return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;

2391   }

2392

2393   /**

2394    * <p>Checks if the CharSequence contains only certaincharacters.</p>

2395    *

2396    * <p>A {@code null} CharSequence will return {@code false}.

2397    * A {@code null} valid character String will return {@code false}.

2398    * An empty String (length()=0) always returns {@code true}.</p>

2399    *

2400    * <pre>

2401    * StringUtils.containsOnly(null, *)      = false

2402    * StringUtils.containsOnly(*, null)      = false

2403    * StringUtils.containsOnly("", *)         = true

2404    * StringUtils.containsOnly("ab", "")      = false

2405    * StringUtils.containsOnly("abab", "abc") = true

2406    * StringUtils.containsOnly("ab1", "abc")  = false

2407    * StringUtils.containsOnly("abz", "abc")  = false

2408    * </pre>

2409    *

2410    * @param cs  the CharSequence tocheck, may be null

2411    * @param validChars  a String ofvalid chars, may be null

2412    * @return true if it only contains valid chars and is non-null

2413    * @since 2.0

2414    * @since 3.0 Changed signature from containsOnly(String, String) tocontainsOnly(CharSequence, String)

2415    */

2416   public static boolean containsOnly(final CharSequence cs, final StringvalidChars) {

2417       if (cs == null || validChars == null) {

2418            return false;

2419       }

2420       return containsOnly(cs, validChars.toCharArray());

2421   }

2422

2423   // ContainsNone

2424   //-----------------------------------------------------------------------

2425   /**

2426    * <p>Checks that the CharSequence does not contain certaincharacters.</p>

2427    *

2428    * <p>A {@code null} CharSequence will return {@code true}.

2429    * A {@code null} invalid character array will return {@code true}.

2430    * An empty CharSequence (length()=0) always returns true.</p>

2431    *

2432    * <pre>

2433    * StringUtils.containsNone(null, *)      = true

2434    * StringUtils.containsNone(*, null)      = true

2435    * StringUtils.containsNone("", *)         = true

2436    * StringUtils.containsNone("ab", '')      = true

2437    * StringUtils.containsNone("abab", 'xyz') = true

2438    * StringUtils.containsNone("ab1", 'xyz')  = true

2439    * StringUtils.containsNone("abz", 'xyz')  = false

2440    * </pre>

2441    *

2442    * @param cs  the CharSequence tocheck, may be null

2443    * @param searchChars  an array ofinvalid chars, may be null

2444    * @return true if it contains none of the invalid chars, or is null

2445    * @since 2.0

2446    * @since 3.0 Changed signature from containsNone(String, char[]) tocontainsNone(CharSequence, char...)

2447    */

2448   public static boolean containsNone(final CharSequence cs, final char...searchChars) {

2449       if (cs == null || searchChars == null) {

2450           return true;

2451       }

2452       final int csLen = cs.length();

2453       final int csLast = csLen - 1;

2454       final int searchLen = searchChars.length;

2455       final int searchLast = searchLen - 1;

2456       for (int i = 0; i < csLen; i++) {

2457            final char ch = cs.charAt(i);

2458            for (int j = 0; j < searchLen;j++) {

2459                if (searchChars[j] == ch) {

2460                    if(Character.isHighSurrogate(ch)) {

2461                        if (j == searchLast) {

2462                            // missing lowsurrogate, fine, like String.indexOf(String)

2463                            return false;

2464                        }

2465                        if (i < csLast&& searchChars[j + 1] == cs.charAt(i + 1)) {

2466                            return false;

2467                        }

2468                    } else {

2469                        // ch is in the BasicMultilingual Plane

2470                        return false;

2471                    }

2472                }

2473            }

2474       }

2475       return true;

2476   }

2477

2478   /**

2479    * <p>Checks that the CharSequence does not contain certaincharacters.</p>

2480    *

2481    * <p>A {@code null} CharSequence will return {@code true}.

2482    * A {@code null} invalid character array will return {@code true}.

2483    * An empty String ("") always returns true.</p>

2484    *

2485    * <pre>

2486    * StringUtils.containsNone(null, *)      = true

2487    * StringUtils.containsNone(*, null)      = true

2488    * StringUtils.containsNone("", *)         = true

2489    * StringUtils.containsNone("ab", "")      = true

2490    * StringUtils.containsNone("abab", "xyz") = true

2491    * StringUtils.containsNone("ab1", "xyz")  = true

2492    * StringUtils.containsNone("abz", "xyz")  = false

2493    * </pre>

2494    *

2495    * @param cs  the CharSequence tocheck, may be null

2496    * @param invalidChars  a String ofinvalid chars, may be null

2497    * @return true if it contains none of the invalid chars, or is null

2498    * @since 2.0

2499    * @since 3.0 Changed signature from containsNone(String, String) tocontainsNone(CharSequence, String)

2500    */

2501   public static boolean containsNone(final CharSequence cs, final StringinvalidChars) {

2502       if (cs == null || invalidChars == null) {

2503            return true;

2504       }

2505       return containsNone(cs, invalidChars.toCharArray());

2506   }

2507

2508   // IndexOfAny strings

2509   //-----------------------------------------------------------------------

2510   /**

2511    * <p>Find the first index of any of a set of potentialsubstrings.</p>

2512    *

2513    * <p>A {@code null} CharSequence will return {@code -1}.

2514    * A {@code null} or zero length search array will return {@code -1}.

2515    * A {@code null} search array entry will be ignored, but a search

2516    * array containing "" will return {@code 0} if {@code str} isnot

2517    * null. This method uses {@link String#indexOf(String)} ifpossible.</p>

2518    *

2519    * <pre>

2520    * StringUtils.indexOfAny(null, *)                     = -1

2521    * StringUtils.indexOfAny(*, null)                     = -1

2522    * StringUtils.indexOfAny(*, [])                       = -1

2523    * StringUtils.indexOfAny("zzabyycdxx",["ab","cd"])   = 2

2524    * StringUtils.indexOfAny("zzabyycdxx",["cd","ab"])   = 2

2525    * StringUtils.indexOfAny("zzabyycdxx",["mn","op"])   = -1

2526    * StringUtils.indexOfAny("zzabyycdxx",["zab","aby"]) = 1

2527    * StringUtils.indexOfAny("zzabyycdxx", [""])          = 0

2528    * StringUtils.indexOfAny("", [""])                    = 0

2529    * StringUtils.indexOfAny("", ["a"])                   = -1

2530    * </pre>

2531    *

2532    * @param str  the CharSequence tocheck, may be null

2533    * @param searchStrs  theCharSequences to search for, may be null

2534    * @return the first index of any of the searchStrs in str, -1 if nomatch

2535    * @since 3.0 Changed signature from indexOfAny(String, String[]) toindexOfAny(CharSequence, CharSequence...)

2536    */

2537   public static int indexOfAny(final CharSequence str, finalCharSequence... searchStrs) {

2538       if (str == null || searchStrs == null) {

2539            return INDEX_NOT_FOUND;

2540       }

2541

2542       // String's can't have a MAX_VALUEth index.

2543       int ret = Integer.MAX_VALUE;

2544

2545       int tmp = 0;

2546       for (final CharSequence search : searchStrs) {

2547            if (search == null) {

2548                continue;

2549            }

2550            tmp =CharSequenceUtils.indexOf(str, search, 0);

2551            if (tmp == INDEX_NOT_FOUND) {

2552                continue;

2553            }

2554

2555            if (tmp < ret) {

2556                ret = tmp;

2557            }

2558       }

2559

2560       return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;

2561   }

2562

2563   /**

2564    * <p>Find the latest index of any of a set of potentialsubstrings.</p>

2565    *

2566    * <p>A {@code null} CharSequence will return {@code -1}.

2567    * A {@code null} search array will return {@code -1}.

2568    * A {@code null} or zero length search array entry will be ignored,

2569    * but a search array containing "" will return the length of{@code str}

2570    * if {@code str} is not null. This method uses {@linkString#indexOf(String)} if possible</p>

2571    *

2572    * <pre>

2573    * StringUtils.lastIndexOfAny(null, *)                   = -1

2574    * StringUtils.lastIndexOfAny(*, null)                   = -1

2575    * StringUtils.lastIndexOfAny(*, [])                     = -1

2576    * StringUtils.lastIndexOfAny(*, [null])                 = -1

2577    * StringUtils.lastIndexOfAny("zzabyycdxx",["ab","cd"]) = 6

2578    * StringUtils.lastIndexOfAny("zzabyycdxx",["cd","ab"]) = 6

2579    * StringUtils.lastIndexOfAny("zzabyycdxx",["mn","op"]) = -1

2580    * StringUtils.lastIndexOfAny("zzabyycdxx",["mn","op"]) = -1

2581    * StringUtils.lastIndexOfAny("zzabyycdxx",["mn",""])   = 10

2582    * </pre>

2583    *

2584    * @param str  the CharSequence tocheck, may be null

2585    * @param searchStrs  theCharSequences to search for, may be null

2586    * @return the last index of any of the CharSequences, -1 if no match

2587    * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) tolastIndexOfAny(CharSequence, CharSequence)

2588    */

2589   public static int lastIndexOfAny(final CharSequence str, finalCharSequence... searchStrs) {

2590       if (str == null || searchStrs == null) {

2591            return INDEX_NOT_FOUND;

2592       }

2593       int ret = INDEX_NOT_FOUND;

2594       int tmp = 0;

2595       for (final CharSequence search : searchStrs) {

2596            if (search == null) {

2597                continue;

2598            }

2599            tmp =CharSequenceUtils.lastIndexOf(str, search, str.length());

2600            if (tmp > ret) {

2601                ret = tmp;

2602            }

2603       }

2604       return ret;

2605   }

2606

2607   // Substring

2608   //-----------------------------------------------------------------------

2609   /**

2610    * <p>Gets a substring from the specified String avoidingexceptions.</p>

2611    *

2612    * <p>A negative start position can be used to start {@code n}

2613    * characters from the end of the String.</p>

2614    *

2615    * <p>A {@code null} String will return {@code null}.

2616    * An empty ("") String will return "".</p>

2617    *

2618    * <pre>

2619    * StringUtils.substring(null, *)  = null

2620    * StringUtils.substring("", *)     = ""

2621    * StringUtils.substring("abc", 0)  = "abc"

2622    * StringUtils.substring("abc", 2)  = "c"

2623    * StringUtils.substring("abc", 4)  = ""

2624    * StringUtils.substring("abc", -2) = "bc"

2625    * StringUtils.substring("abc", -4) = "abc"

2626    * </pre>

2627    *

2628    * @param str  the String to getthe substring from, may be null

2629    * @param start  the position tostart from, negative means

2630    *  count back from the end of theString by this many characters

2631    * @return substring from start position, {@code null} if null Stringinput

2632    */

2633   public static String substring(final String str, int start) {

2634       if (str == null) {

2635            return null;

2636       }

2637

2638       // handle negatives, which means last n characters

2639       if (start < 0) {

2640            start = str.length() + start; //remember start is negative

2641       }

2642

2643       if (start < 0) {

2644            start = 0;

2645       }

2646       if (start > str.length()) {

2647            return EMPTY;

2648       }

2649

2650       return str.substring(start);

2651   }

2652

2653   /**

2654    * <p>Gets a substring from the specified String avoidingexceptions.</p>

2655    *

2656    * <p>A negative start position can be used to start/end {@code n}

2657    * characters from the end of the String.</p>

2658    *

2659    * <p>The returned substring starts with the character in the{@code start}

2660    * position and ends before the {@code end} position. All positioncounting is

2661    * zero-based -- i.e., to start at the beginning of the string use

2662    * {@code start = 0}. Negative start and end positions can be used to

2663    * specify offsets relative to the end of the String.</p>

2664    *

2665    * <p>If {@code start} is not strictly to the left of {@code end},""

2666    * is returned.</p>

2667    *

2668    * <pre>

2669    * StringUtils.substring(null, *, *)   = null

2670    * StringUtils.substring("", * ,  *)    ="";

2671    * StringUtils.substring("abc", 0, 2)   = "ab"

2672    * StringUtils.substring("abc", 2, 0)   = ""

2673    * StringUtils.substring("abc", 2, 4)   = "c"

2674    * StringUtils.substring("abc", 4, 6)   = ""

2675    * StringUtils.substring("abc", 2, 2)   = ""

2676    * StringUtils.substring("abc", -2, -1) = "b"

2677    * StringUtils.substring("abc", -4, 2)  = "ab"

2678    * </pre>

2679    *

2680    * @param str  the String to getthe substring from, may be null

2681    * @param start  the position tostart from, negative means

2682    *  count back from the end of theString by this many characters

2683    * @param end  the position to endat (exclusive), negative means

2684    *  count back from the end of theString by this many characters

2685    * @return substring from start position to end position,

2686    *  {@code null} if null Stringinput

2687    */

2688   public static String substring(final String str, int start, int end) {

2689       if (str == null) {

2690            return null;

2691       }

2692

2693       // handle negatives

2694       if (end < 0) {

2695            end = str.length() + end; //remember end is negative

2696       }

2697       if (start < 0) {

2698            start = str.length() + start; //remember start is negative

2699       }

2700

2701       // check length next

2702       if (end > str.length()) {

2703            end = str.length();

2704       }

2705

2706       // if start is greater than end, return ""

2707       if (start > end) {

2708            return EMPTY;

2709       }

2710

2711       if (start < 0) {

2712            start = 0;

2713       }

2714       if (end < 0) {

2715            end = 0;

2716       }

2717

2718       return str.substring(start, end);

2719   }

2720

2721   // Left/Right/Mid

2722   //-----------------------------------------------------------------------

2723   /**

2724    * <p>Gets the leftmost {@code len} characters of aString.</p>

2725    *

2726    * <p>If {@code len} characters are not available, or the

2727    * String is {@code null}, the String will be returned without

2728    * an exception. An empty String is returned if len isnegative.</p>

2729    *

2730    * <pre>

2731    * StringUtils.left(null, *)    =null

2732    * StringUtils.left(*, -ve)     =""

2733    * StringUtils.left("", *)     = ""

2734    * StringUtils.left("abc", 0)  = ""

2735    * StringUtils.left("abc", 2)  = "ab"

2736    * StringUtils.left("abc", 4)  = "abc"

2737    * </pre>

2738    *

2739    * @param str  the String to getthe leftmost characters from, may be null

2740    * @param len  the length of therequired String

2741    * @return the leftmost characters, {@code null} if null String input

2742    */

2743   public static String left(final String str, final int len) {

2744       if (str == null) {

2745            return null;

2746       }

2747       if (len < 0) {

2748            return EMPTY;

2749       }

2750       if (str.length() <= len) {

2751            return str;

2752       }

2753       return str.substring(0, len);

2754   }

2755

2756   /**

2757    * <p>Gets the rightmost {@code len} characters of aString.</p>

2758    *

2759    * <p>If {@code len} characters are not available, or the String

2760    * is {@code null}, the String will be returned without an

2761    * an exception. An empty String is returned if len isnegative.</p>

2762    *

2763    * <pre>

2764    * StringUtils.right(null, *)    =null

2765    * StringUtils.right(*, -ve)     =""

2766    * StringUtils.right("", *)     = ""

2767    * StringUtils.right("abc", 0)  = ""

2768    * StringUtils.right("abc", 2)  = "bc"

2769    * StringUtils.right("abc", 4)  = "abc"

2770    * </pre>

2771    *

2772    * @param str  the String to getthe rightmost characters from, may be null

2773    * @param len  the length of therequired String

2774    * @return the rightmost characters, {@code null} if null String input

2775     */

2776   public static String right(final String str, final int len) {

2777       if (str == null) {

2778            return null;

2779       }

2780       if (len < 0) {

2781            return EMPTY;

2782       }

2783       if (str.length() <= len) {

2784            return str;

2785       }

2786       return str.substring(str.length() - len);

2787   }

2788

2789   /**

2790    * <p>Gets {@code len} characters from the middle of aString.</p>

2791    *

2792    * <p>If {@code len} characters are not available, the remainder

2793    * of the String will be returned without an exception. If the

2794    * String is {@code null}, {@code null} will be returned.

2795    * An empty String is returned if len is negative or exceeds the

2796    * length of {@code str}.</p>

2797    *

2798    * <pre>

2799    * StringUtils.mid(null, *, *)    =null

2800    * StringUtils.mid(*, *, -ve)     =""

2801    * StringUtils.mid("", 0, *)      = ""

2802    * StringUtils.mid("abc", 0, 2)   = "ab"

2803    * StringUtils.mid("abc", 0, 4)   = "abc"

2804    * StringUtils.mid("abc", 2, 4)   = "c"

2805    * StringUtils.mid("abc", 4, 2)   = ""

2806    * StringUtils.mid("abc", -2, 2)  = "ab"

2807    * </pre>

2808    *

2809    * @param str  the String to getthe characters from, may be null

2810    * @param pos  the position tostart from, negative treated as zero

2811    * @param len  the length of therequired String

2812    * @return the middle characters, {@code null} if null String input

2813    */

2814   public static String mid(final String str, int pos, final int len) {

2815       if (str == null) {

2816            return null;

2817       }

2818       if (len < 0 || pos > str.length()) {

2819            return EMPTY;

2820       }

2821       if (pos < 0) {

2822            pos = 0;

2823       }

2824       if (str.length() <= pos + len) {

2825            return str.substring(pos);

2826       }

2827       return str.substring(pos, pos + len);

2828   }

2829

2830   // SubStringAfter/SubStringBefore

2831   //-----------------------------------------------------------------------

2832   /**

2833    * <p>Gets the substring before the first occurrence of aseparator.

2834    * The separator is not returned.</p>

2835    *

2836    * <p>A {@code null} string input will return {@code null}.

2837    * An empty ("") string input will return the empty string.

2838    * A {@code null} separator will return the input string.</p>

2839    *

2840    * <p>If nothing is found, the string input is returned.</p>

2841    *

2842    * <pre>

2843    * StringUtils.substringBefore(null, *)      = null

2844    * StringUtils.substringBefore("", *)        = ""

2845    * StringUtils.substringBefore("abc", "a")   = ""

2846    * StringUtils.substringBefore("abcba", "b") ="a"

2847    * StringUtils.substringBefore("abc", "c")   = "ab"

2848    * StringUtils.substringBefore("abc", "d")   = "abc"

2849    * StringUtils.substringBefore("abc", "")    = ""

2850    * StringUtils.substringBefore("abc", null)  = "abc"

2851    * </pre>

2852    *

2853    * @param str  the String to get asubstring from, may be null

2854    * @param separator  the String tosearch for, may be null

2855    * @return the substring before the first occurrence of the separator,

2856    *  {@code null} if null Stringinput

2857    * @since 2.0

2858    */

2859   public static String substringBefore(final String str, final Stringseparator) {

2860       if (isEmpty(str) || separator == null) {

2861            return str;

2862       }

2863       if (separator.isEmpty()) {

2864            return EMPTY;

2865       }

2866       final int pos = str.indexOf(separator);

2867       if (pos == INDEX_NOT_FOUND) {

2868            return str;

2869       }

2870       return str.substring(0, pos);

2871   }

2872

2873   /**

2874    * <p>Gets the substring after the first occurrence of a separator.

2875    * The separator is not returned.</p>

2876    *

2877    * <p>A {@code null} string input will return {@code null}.

2878    * An empty ("") string input will return the empty string.

2879    * A {@code null} separator will return the empty string if the

2880    * input string is not {@code null}.</p>

2881    *

2882    * <p>If nothing is found, the empty string is returned.</p>

2883    *

2884    * <pre>

2885    * StringUtils.substringAfter(null, *)      = null

2886    * StringUtils.substringAfter("", *)        = ""

2887    * StringUtils.substringAfter(*, null)      = ""

2888    * StringUtils.substringAfter("abc", "a")   = "bc"

2889    * StringUtils.substringAfter("abcba", "b") ="cba"

2890    * StringUtils.substringAfter("abc", "c")   = ""

2891    * StringUtils.substringAfter("abc", "d")   = ""

2892    * StringUtils.substringAfter("abc", "")    = "abc"

2893    * </pre>

2894    *

2895    * @param str  the String to get asubstring from, may be null

2896    * @param separator  the String tosearch for, may be null

2897    * @return the substring after the first occurrence of the separator,

2898    *  {@code null} if null Stringinput

2899    * @since 2.0

2900    */

2901   public static String substringAfter(final String str, final Stringseparator) {

2902       if (isEmpty(str)) {

2903            return str;

2904       }

2905       if (separator == null) {

2906            return EMPTY;

2907       }

2908       final int pos = str.indexOf(separator);

2909       if (pos == INDEX_NOT_FOUND) {

2910            return EMPTY;

2911       }

2912       return str.substring(pos + separator.length());

2913   }

2914

2915   /**

2916    * <p>Gets the substring before the last occurrence of a separator.

2917    * The separator is not returned.</p>

2918    *

2919    * <p>A {@code null} string input will return {@code null}.

2920    * An empty ("") string input will return the empty string.

2921    * An empty or {@code null} separator will return the inputstring.</p>

2922    *

2923    * <p>If nothing is found, the string input is returned.</p>

2924    *

2925    * <pre>

2926    * StringUtils.substringBeforeLast(null, *)      = null

2927    * StringUtils.substringBeforeLast("", *)        = ""

2928    * StringUtils.substringBeforeLast("abcba", "b") ="abc"

2929    * StringUtils.substringBeforeLast("abc", "c")   = "ab"

2930    * StringUtils.substringBeforeLast("a", "a")     = ""

2931    * StringUtils.substringBeforeLast("a", "z")     = "a"

2932    * StringUtils.substringBeforeLast("a", null)    = "a"

2933    * StringUtils.substringBeforeLast("a", "")      = "a"

2934    * </pre>

2935    *

2936    * @param str  the String to get asubstring from, may be null

2937    * @param separator  the String tosearch for, may be null

2938    * @return the substring before the last occurrence of the separator,

2939    *  {@code null} if null Stringinput

2940    * @since 2.0

2941    */

2942   public static String substringBeforeLast(final String str, final Stringseparator) {

2943       if (isEmpty(str) || isEmpty(separator)) {

2944            return str;

2945       }

2946       final int pos = str.lastIndexOf(separator);

2947       if (pos == INDEX_NOT_FOUND) {

2948            return str;

2949       }

2950       return str.substring(0, pos);

2951   }

2952

2953   /**

2954    * <p>Gets the substring after the last occurrence of a separator.

2955    * The separator is not returned.</p>

2956    *

2957    * <p>A {@code null} string input will return {@code null}.

2958    * An empty ("") string input will return the empty string.

2959    * An empty or {@code null} separator will return the empty string if

2960    * the input string is not {@code null}.</p>

2961    *

2962    * <p>If nothing is found, the empty string is returned.</p>

2963    *

2964    * <pre>

2965    * StringUtils.substringAfterLast(null, *)      = null

2966    * StringUtils.substringAfterLast("", *)        = ""

2967    * StringUtils.substringAfterLast(*, "")        = ""

2968    * StringUtils.substringAfterLast(*, null)      = ""

2969    * StringUtils.substringAfterLast("abc", "a")   = "bc"

2970    * StringUtils.substringAfterLast("abcba", "b") ="a"

2971    * StringUtils.substringAfterLast("abc", "c")   = ""

2972    * StringUtils.substringAfterLast("a", "a")     = ""

2973    * StringUtils.substringAfterLast("a", "z")     = ""

2974    * </pre>

2975    *

2976    * @param str  the String to get asubstring from, may be null

2977    * @param separator  the String tosearch for, may be null

2978    * @return the substring after the last occurrence of the separator,

2979    *  {@code null} if null Stringinput

2980    * @since 2.0

2981    */

2982   public static String substringAfterLast(final String str, final Stringseparator) {

2983       if (isEmpty(str)) {

2984            return str;

2985       }

2986       if (isEmpty(separator)) {

2987            return EMPTY;

2988       }

2989       final int pos = str.lastIndexOf(separator);

2990       if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()){

2991            return EMPTY;

2992       }

2993       return str.substring(pos + separator.length());

2994   }

2995

2996   // Substring between

2997   //-----------------------------------------------------------------------

2998   /**

2999    * <p>Gets the String that is nested in between two instances ofthe

3000    * same String.</p>

3001    *

3002    * <p>A {@code null} input String returns {@code null}.

3003    * A {@code null} tag returns {@code null}.</p>

3004    *

3005    * <pre>

3006    * StringUtils.substringBetween(null, *)            = null

3007    * StringUtils.substringBetween("", "")             = ""

3008    * StringUtils.substringBetween("", "tag")          = null

3009    * StringUtils.substringBetween("tagabctag", null)  = null

3010    * StringUtils.substringBetween("tagabctag", "")    = ""

3011    * StringUtils.substringBetween("tagabctag", "tag") ="abc"

3012    * </pre>

3013    *

3014    * @param str  the Stringcontaining the substring, may be null

3015    * @param tag  the String beforeand after the substring, may be null

3016    * @return the substring, {@code null} if no match

3017    * @since 2.0

3018    */

3019   public static String substringBetween(final String str, final Stringtag) {

3020       return substringBetween(str, tag, tag);

3021   }

3022

3023   /**

3024    * <p>Gets the String that is nested in between two Strings.

3025    * Only the first match is returned.</p>

3026    *

3027    * <p>A {@code null} input String returns {@code null}.

3028    * A {@code null} open/close returns {@code null} (no match).

3029    * An empty ("") open and close returns an emptystring.</p>

3030    *

3031     * <pre>

3032    * StringUtils.substringBetween("wx[b]yz", "[","]") = "b"

3033    * StringUtils.substringBetween(null, *, *)          = null

3034    * StringUtils.substringBetween(*, null, *)          = null

3035    * StringUtils.substringBetween(*, *, null)          = null

3036    * StringUtils.substringBetween("", "","")          = ""

3037    * StringUtils.substringBetween("", "","]")         = null

3038    * StringUtils.substringBetween("", "[","]")        = null

3039    * StringUtils.substringBetween("yabcz", "","")     = ""

3040    * StringUtils.substringBetween("yabcz", "y","z")   = "abc"

3041    * StringUtils.substringBetween("yabczyabcz", "y","z")   = "abc"

3042    * </pre>

3043    *

3044    * @param str  the Stringcontaining the substring, may be null

3045    * @param open  the String beforethe substring, may be null

3046    * @param close  the String afterthe substring, may be null

3047    * @return the substring, {@code null} if no match

3048    * @since 2.0

3049    */

3050   public static String substringBetween(final String str, final Stringopen, final String close) {

3051       if (str == null || open == null || close == null) {

3052            return null;

3053       }

3054       final int start = str.indexOf(open);

3055       if (start != INDEX_NOT_FOUND) {

3056            final int end = str.indexOf(close,start + open.length());

3057            if (end != INDEX_NOT_FOUND) {

3058                return str.substring(start +open.length(), end);

3059            }

3060       }

3061       return null;

3062   }

3063

3064   /**

3065    * <p>Searches a String for substrings delimited by a start and endtag,

3066    * returning all matching substrings in an array.</p>

3067    *

3068    * <p>A {@code null} input String returns {@code null}.

3069    * A {@code null} open/close returns {@code null} (no match).

3070    * An empty ("") open/close returns {@code null} (nomatch).</p>

3071    *

3072    * <pre>

3073    * StringUtils.substringsBetween("[a][b][c]", "[","]") = ["a","b","c"]

3074    * StringUtils.substringsBetween(null, *, *)            = null

3075    * StringUtils.substringsBetween(*, null, *)            = null

3076    * StringUtils.substringsBetween(*, *, null)            = null

3077    * StringUtils.substringsBetween("", "[","]")          = []

3078    * </pre>

3079    *

3080    * @param str  the Stringcontaining the substrings, null returns null, empty returns empty

3081    * @param open  the Stringidentifying the start of the substring, empty returns null

3082    * @param close  the Stringidentifying the end of the substring, empty returns null

3083    * @return a String Array of substrings, or {@code null} if no match

3084    * @since 2.3

3085    */

3086   public static String[] substringsBetween(final String str, final Stringopen, final String close) {

3087       if (str == null || isEmpty(open) || isEmpty(close)) {

3088            return null;

3089       }

3090       final int strLen = str.length();

3091       if (strLen == 0) {

3092            returnArrayUtils.EMPTY_STRING_ARRAY;

3093       }

3094       final int closeLen = close.length();

3095       final int openLen = open.length();

3096       final List<String> list = new ArrayList<>();

3097       int pos = 0;

3098       while (pos < strLen - closeLen) {

3099            int start = str.indexOf(open, pos);

3100            if (start < 0) {

3101                break;

3102            }

3103            start += openLen;

3104            final int end = str.indexOf(close,start);

3105            if (end < 0) {

3106                break;

3107            }

3108            list.add(str.substring(start,end));

3109            pos = end + closeLen;

3110       }

3111       if (list.isEmpty()) {

3112            return null;

3113       }

3114       return list.toArray(new String [list.size()]);

3115   }

3116

3117   // Nested extraction

3118   //-----------------------------------------------------------------------

3119

3120   // Splitting

3121   //-----------------------------------------------------------------------

3122   /**

3123    * <p>Splits the provided text into an array, using whitespace asthe

3124    * separator.

3125    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

3126    *

3127    * <p>The separator is not included in the returned String array.

3128    * Adjacent separators are treated as one separator.

3129    * For more control over the split use the StrTokenizer class.</p>

3130    *

3131    * <p>A {@code null} input String returns {@code null}.</p>

3132    *

3133    * <pre>

3134    * StringUtils.split(null)       =null

3135    * StringUtils.split("")        = []

3136    * StringUtils.split("abc def") = ["abc", "def"]

3137    * StringUtils.split("abc def") = ["abc", "def"]

3138    * StringUtils.split(" abc ")   = ["abc"]

3139    * </pre>

3140    *

3141    * @param str  the String to parse,may be null

3142    * @return an array of parsed Strings, {@code null} if null String input

3143    */

3144   public static String[] split(final String str) {

3145       return split(str, null, -1);

3146   }

3147

3148   /**

3149    * <p>Splits the provided text into an array, separator specified.

3150    * This is an alternative to using StringTokenizer.</p>

3151    *

3152    * <p>The separator is not included in the returned String array.

3153    * Adjacent separators are treated as one separator.

3154    * For more control over the split use the StrTokenizer class.</p>

3155    *

3156    * <p>A {@code null} input String returns {@code null}.</p>

3157    *

3158    * <pre>

3159    * StringUtils.split(null, *)        = null

3160    * StringUtils.split("", *)           = []

3161    * StringUtils.split("a.b.c", '.')    = ["a", "b","c"]

3162    * StringUtils.split("a..b.c", '.')   = ["a", "b","c"]

3163    * StringUtils.split("a:b:c", '.')    = ["a:b:c"]

3164    * StringUtils.split("a b c", ' ')    = ["a", "b","c"]

3165    * </pre>

3166    *

3167    * @param str  the String to parse,may be null

3168    * @param separatorChar  thecharacter used as the delimiter

3169    * @return an array of parsed Strings, {@code null} if null String input

3170    * @since 2.0

3171    */

3172   public static String[] split(final String str, final char separatorChar){

3173       return splitWorker(str, separatorChar, false);

3174   }

3175

3176   /**

3177    * <p>Splits the provided text into an array, separators specified.

3178    * This is an alternative to using StringTokenizer.</p>

3179    *

3180    * <p>The separator is not included in the returned String array.

3181    * Adjacent separators are treated as one separator.

3182    * For more control over the split use the StrTokenizer class.</p>

3183    *

3184    * <p>A {@code null} input String returns {@code null}.

3185    * A {@code null} separatorChars splits on whitespace.</p>

3186    *

3187    * <pre>

3188    * StringUtils.split(null, *)        = null

3189    * StringUtils.split("", *)           = []

3190    * StringUtils.split("abc def", null) = ["abc","def"]

3191    * StringUtils.split("abc def", " ")  = ["abc", "def"]

3192    * StringUtils.split("abc def", " ") = ["abc", "def"]

3193    * StringUtils.split("ab:cd:ef", ":") =["ab", "cd", "ef"]

3194    * </pre>

3195    *

3196    * @param str  the String to parse,may be null

3197    * @param separatorChars  thecharacters used as the delimiters,

3198    *  {@code null} splits onwhitespace

3199    * @return an array of parsed Strings, {@code null} if null String input

3200    */

3201   public static String[] split(final String str, final StringseparatorChars) {

3202       return splitWorker(str, separatorChars, -1, false);

3203   }

3204

3205   /**

3206    * <p>Splits the provided text into an array with a maximum length,

3207    * separators specified.</p>

3208    *

3209    * <p>The separator is not included in the returned String array.

3210    * Adjacent separators are treated as one separator.</p>

3211    *

3212    * <p>A {@code null} input String returns {@code null}.

3213    * A {@code null} separatorChars splits on whitespace.</p>

3214    *

3215    * <p>If more than {@code max} delimited substrings are found, thelast

3216    * returned string includes all characters after the first {@code max -1}

3217    * returned strings (including separator characters).</p>

3218    *

3219    * <pre>

3220    * StringUtils.split(null, *, *)            = null

3221    * StringUtils.split("", *, *)              = []

3222    * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd","ef"]

3223    * StringUtils.split("ab   cdef", null, 0) = ["ab", "cd", "ef"]

3224    * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd","ef"]

3225    * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]

3226    * </pre>

3227    *

3228    * @param str  the String to parse,may be null

3229    * @param separatorChars  thecharacters used as the delimiters,

3230    *  {@code null} splits onwhitespace

3231    * @param max  the maximum numberof elements to include in the

3232    *  array. A zero or negative valueimplies no limit

3233    * @return an array of parsed Strings, {@code null} if null String input

3234    */

3235   public static String[] split(final String str, final StringseparatorChars, final int max) {

3236       return splitWorker(str, separatorChars, max, false);

3237   }

3238

3239   /**

3240    * <p>Splits the provided text into an array, separator stringspecified.</p>

3241    *

3242    * <p>The separator(s) will not be included in the returned Stringarray.

3243    * Adjacent separators are treated as one separator.</p>

3244    *

3245    * <p>A {@code null} input String returns {@code null}.

3246    * A {@code null} separator splits on whitespace.</p>

3247    *

3248    * <pre>

3249    * StringUtils.splitByWholeSeparator(null, *)               = null

3250    * StringUtils.splitByWholeSeparator("", *)                 = []

3251    * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de","fg"]

3252    * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de","fg"]

3253    * StringUtils.splitByWholeSeparator("ab:cd:ef",":")       = ["ab","cd", "ef"]

3254    * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef","-!-") = ["ab", "cd", "ef"]

3255    * </pre>

3256    *

3257    * @param str  the String to parse,may be null

3258    * @param separator  Stringcontaining the String to be used as a delimiter,

3259    *  {@code null} splits onwhitespace

3260    * @return an array of parsed Strings, {@code null} if null String wasinput

3261    */

3262   public static String[] splitByWholeSeparator(final String str, finalString separator) {

3263       return splitByWholeSeparatorWorker( str, separator, -1, false ) ;

3264   }

3265

3266   /**

3267    * <p>Splits the provided text into an array, separator stringspecified.

3268    * Returns a maximum of {@code max} substrings.</p>

3269    *

3270    * <p>The separator(s) will not be included in the returned Stringarray.

3271    * Adjacent separators are treated as one separator.</p>

3272    *

3273    * <p>A {@code null} input String returns {@code null}.

3274    * A {@code null} separator splits on whitespace.</p>

3275    *

3276    * <pre>

3277    * StringUtils.splitByWholeSeparator(null, *, *)               = null

3278    * StringUtils.splitByWholeSeparator("", *, *)                 = []

3279    * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de","fg"]

3280    * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de","fg"]

3281    * StringUtils.splitByWholeSeparator("ab:cd:ef", ":",2)       = ["ab","cd:ef"]

3282    * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef","-!-", 5) = ["ab", "cd", "ef"]

3283    * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef","-!-", 2) = ["ab", "cd-!-ef"]

3284    * </pre>

3285    *

3286    * @param str  the String to parse,may be null

3287    * @param separator  Stringcontaining the String to be used as a delimiter,

3288    *  {@code null} splits onwhitespace

3289    * @param max  the maximum numberof elements to include in the returned

3290    *  array. A zero or negative valueimplies no limit.

3291    * @return an array of parsed Strings, {@code null} if null String wasinput

3292    */

3293   public static String[] splitByWholeSeparator( final String str, finalString separator, final int max) {

3294       return splitByWholeSeparatorWorker(str, separator, max, false);

3295   }

3296

3297   /**

3298    * <p>Splits the provided text into an array, separator stringspecified. </p>

3299    *

3300    * <p>The separator is not included in the returned String array.

3301    * Adjacent separators are treated as separators for empty tokens.

3302    * For more control over the split use the StrTokenizer class.</p>

3303    *

3304    * <p>A {@code null} input String returns {@code null}.

3305    * A {@code null} separator splits on whitespace.</p>

3306    *

3307    * <pre>

3308    * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null

3309    * StringUtils.splitByWholeSeparatorPreserveAllTokens("",*)                 = []

3310    * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab defg", null)      = ["ab","de", "fg"]

3311    * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "","", "de", "fg"]

3312    *StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef",":")       = ["ab","cd", "ef"]

3313    *StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef","-!-") = ["ab", "cd", "ef"]

3314    * </pre>

3315    *

3316    * @param str  the String to parse,may be null

3317    * @param separator  Stringcontaining the String to be used as a delimiter,

3318    *  {@code null} splits onwhitespace

3319    * @return an array of parsed Strings, {@code null} if null String wasinput

3320    * @since 2.4

3321    */

3322   public static String[] splitByWholeSeparatorPreserveAllTokens(finalString str, final String separator) {

3323       return splitByWholeSeparatorWorker(str, separator, -1, true);

3324   }

3325

3326   /**

3327    * <p>Splits the provided text into an array, separator stringspecified.

3328    * Returns a maximum of {@code max} substrings.</p>

3329    *

3330    * <p>The separator is not included in the returned String array.

3331    * Adjacent separators are treated as separators for empty tokens.

3332    * For more control over the split use the StrTokenizer class.</p>

3333    *

3334    * <p>A {@code null} input String returns {@code null}.

3335    * A {@code null} separator splits on whitespace.</p>

3336    *

3337    * <pre>

3338    * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null

3339    * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *,*)                 = []

3340    * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab defg", null, 0)      =["ab", "de", "fg"]

3341    * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "","", "de", "fg"]

3342    *StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef",":", 2)       =["ab", "cd:ef"]

3343    *StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef","-!-", 5) = ["ab", "cd", "ef"]

3344    * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef","-!-", 2) = ["ab", "cd-!-ef"]

3345    * </pre>

3346    *

3347    * @param str  the String to parse,may be null

3348    * @param separator  Stringcontaining the String to be used as a delimiter,

3349    *  {@code null} splits onwhitespace

3350    * @param max  the maximum numberof elements to include in the returned

3351    *  array. A zero or negative valueimplies no limit.

3352    * @return an array of parsed Strings, {@code null} if null String wasinput

3353    * @since 2.4

3354    */

3355   public static String[] splitByWholeSeparatorPreserveAllTokens(finalString str, final String separator, final int max) {

3356       return splitByWholeSeparatorWorker(str, separator, max, true);

3357   }

3358

3359   /**

3360    * Performs the logic for the {@codesplitByWholeSeparatorPreserveAllTokens} methods.

3361    *

3362    * @param str  the String to parse,may be {@code null}

3363    * @param separator  Stringcontaining the String to be used as a delimiter,

3364    *  {@code null} splits onwhitespace

3365    * @param max  the maximum numberof elements to include in the returned

3366    *  array. A zero or negative valueimplies no limit.

3367    * @param preserveAllTokens if {@code true}, adjacent separators are

3368    * treated as empty token separators; if {@code false}, adjacent

3369    * separators are treated as one separator.

3370    * @return an array of parsed Strings, {@code null} if null String input

3371    * @since 2.4

3372    */

3373   private static String[] splitByWholeSeparatorWorker(

3374            final String str, final Stringseparator, final int max, final boolean preserveAllTokens) {

3375       if (str == null) {

3376            return null;

3377       }

3378

3379       final int len = str.length();

3380

3381       if (len == 0) {

3382            returnArrayUtils.EMPTY_STRING_ARRAY;

3383       }

3384

3385       if (separator == null || EMPTY.equals(separator)) {

3386            // Split on whitespace.

3387            return splitWorker(str, null, max,preserveAllTokens);

3388       }

3389

3390       final int separatorLength = separator.length();

3391

3392       final ArrayList<String> substrings = new ArrayList<>();

3393       int numberOfSubstrings = 0;

3394       int beg = 0;

3395       int end = 0;

3396       while (end < len) {

3397            end = str.indexOf(separator, beg);

3398

3399            if (end > -1) {

3400                if (end > beg) {

3401                    numberOfSubstrings += 1;

3402

3403                    if (numberOfSubstrings ==max) {

3404                        end = len;

3405                       substrings.add(str.substring(beg));

3406                    } else {

3407                        // The following is OK,because String.substring( beg, end ) excludes

3408                        // the character at the position 'end'.

3409                       substrings.add(str.substring(beg, end));

3410

3411                        // Set the startingpoint for the next search.

3412                        // The following isequivalent to beg = end + (separatorLength - 1) + 1,

3413                        // which is the rightcalculation:

3414                        beg = end +separatorLength;

3415                    }

3416                } else {

3417                    // We found a consecutiveoccurrence of the separator, so skip it.

3418                    if (preserveAllTokens) {

3419                        numberOfSubstrings +=1;

3420                        if (numberOfSubstrings== max) {

3421                            end = len;

3422                           substrings.add(str.substring(beg));

3423                        } else {

3424                           substrings.add(EMPTY);

3425                        }

3426                    }

3427                    beg = end +separatorLength;

3428                }

3429            } else {

3430                // String.substring( beg ) goesfrom 'beg' to the end of the String.

3431               substrings.add(str.substring(beg));

3432                end = len;

3433            }

3434       }

3435

3436       return substrings.toArray(new String[substrings.size()]);

3437   }

3438

3439   //-----------------------------------------------------------------------

3440   /**

3441    * <p>Splits the provided text into an array, using whitespace asthe

3442    * separator, preserving all tokens, including empty tokens created by

3443    * adjacent separators. This is an alternative to using StringTokenizer.

3444    * Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

3445    *

3446    * <p>The separator is not included in the returned String array.

3447    * Adjacent separators are treated as separators for empty tokens.

3448    * For more control over the split use the StrTokenizer class.</p>

3449    *

3450    * <p>A {@code null} input String returns {@code null}.</p>

3451    *

3452    * <pre>

3453    * StringUtils.splitPreserveAllTokens(null)       = null

3454    * StringUtils.splitPreserveAllTokens("")         = []

3455    * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]

3456    * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "","def"]

3457    * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc",""]

3458    * </pre>

3459    *

3460    * @param str  the String to parse,may be {@code null}

3461    * @return an array of parsed Strings, {@code null} if null String input

3462    * @since 2.1

3463    */

3464   public static String[] splitPreserveAllTokens(final String str) {

3465       return splitWorker(str, null, -1, true);

3466   }

3467

3468   /**

3469    * <p>Splits the provided text into an array, separator specified,

3470    * preserving all tokens, including empty tokens created by adjacent

3471    * separators. This is an alternative to using StringTokenizer.</p>

3472    *

3473    * <p>The separator is not included in the returned String array.

3474    * Adjacent separators are treated as separators for empty tokens.

3475    * For more control over the split use the StrTokenizer class.</p>

3476    *

3477    * <p>A {@code null} input String returns {@code null}.</p>

3478    *

3479    * <pre>

3480    * StringUtils.splitPreserveAllTokens(null, *)         = null

3481    * StringUtils.splitPreserveAllTokens("", *)           = []

3482    * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b","c"]

3483    * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "","b", "c"]

3484    * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]

3485    * StringUtils.splitPreserveAllTokens("a\tb\nc", null) =["a", "b", "c"]

3486    * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b","c"]

3487    * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b","c", ""]

3488    * StringUtils.splitPreserveAllTokens("a b c  ", ' ')  = ["a", "b", "c", "", ""]

3489    * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", a", "b","c"]

3490    * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", a","b", "c"]

3491    * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", a", "b","c", ""]

3492    * </pre>

3493    *

3494    * @param str  the String to parse,may be {@code null}

3495    * @param separatorChar  thecharacter used as the delimiter,

3496    *  {@code null} splits onwhitespace

3497    * @return an array of parsed Strings, {@code null} if null String input

3498    * @since 2.1

3499    */

3500   public static String[] splitPreserveAllTokens(final String str, finalchar separatorChar) {

3501       return splitWorker(str, separatorChar, true);

3502   }

3503

3504   /**

3505    * Performs the logic for the {@code split} and

3506    * {@code splitPreserveAllTokens} methods that do not return a

3507    * maximum array length.

3508    *

3509    * @param str  the String to parse,may be {@code null}

3510    * @param separatorChar the separate character

3511    * @param preserveAllTokens if {@code true}, adjacent separators are

3512    * treated as empty token separators; if {@code false}, adjacent

3513    * separators are treated as one separator.

3514    * @return an array of parsed Strings, {@code null} if null String input

3515    */

3516   private static String[] splitWorker(final String str, final charseparatorChar, final boolean preserveAllTokens) {

3517       // Performance tuned for 2.0 (JDK1.4)

3518

3519       if (str == null) {

3520            return null;

3521       }

3522       final int len = str.length();

3523       if (len == 0) {

3524            returnArrayUtils.EMPTY_STRING_ARRAY;

3525       }

3526       final List<String> list = new ArrayList<>();

3527       int i = 0, start = 0;

3528       boolean match = false;

3529       boolean lastMatch = false;

3530       while (i < len) {

3531            if (str.charAt(i) == separatorChar){

3532               if (match ||preserveAllTokens) {

3533                   list.add(str.substring(start, i));

3534                    match = false;

3535                    lastMatch = true;

3536                }

3537                start = ++i;

3538                continue;

3539            }

3540            lastMatch = false;

3541            match = true;

3542            i++;

3543       }

3544       if (match || preserveAllTokens && lastMatch) {

3545            list.add(str.substring(start, i));

3546       }

3547       return list.toArray(new String[list.size()]);

3548   }

3549

3550   /**

3551    * <p>Splits the provided text into an array, separators specified,

3552    * preserving all tokens, including empty tokens created by adjacent

3553    * separators. This is an alternative to using StringTokenizer.</p>

3554    *

3555    * <p>The separator is not included in the returned String array.

3556    * Adjacent separators are treated as separators for empty tokens.

3557    * For more control over the split use the StrTokenizer class.</p>

3558    *

3559    * <p>A {@code null} input String returns {@code null}.

3560    * A {@code null} separatorChars splits on whitespace.</p>

3561    *

3562    * <pre>

3563    * StringUtils.splitPreserveAllTokens(null, *)           = null

3564    * StringUtils.splitPreserveAllTokens("", *)             = []

3565    * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]

3566    * StringUtils.splitPreserveAllTokens("abc def", "")    = ["abc","def"]

3567    * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", def"]

3568    * StringUtils.splitPreserveAllTokens("ab:cd:ef",":")   = ["ab","cd", "ef"]

3569    * StringUtils.splitPreserveAllTokens("ab:cd:ef:",":")  = ["ab","cd", "ef", ""]

3570    * StringUtils.splitPreserveAllTokens("ab:cd:ef::",":") = ["ab", "cd", "ef", "",""]

3571    * StringUtils.splitPreserveAllTokens("ab::cd:ef",":")  = ["ab","", cd", "ef"]

3572    * StringUtils.splitPreserveAllTokens(":cd:ef",":")     = ["",cd", "ef"]

3573    * StringUtils.splitPreserveAllTokens("::cd:ef",":")    = ["","", cd", "ef"]

3574    * StringUtils.splitPreserveAllTokens(":cd:ef:",":")    = ["", cd","ef", ""]

3575    * </pre>

3576    *

3577    * @param str  the String to parse,may be {@code null}

3578    * @param separatorChars  thecharacters used as the delimiters,

3579    *  {@code null} splits onwhitespace

3580    * @return an array of parsed Strings, {@code null} if null String input

3581    * @since 2.1

3582    */

3583   public static String[] splitPreserveAllTokens(final String str, finalString separatorChars) {

3584       return splitWorker(str, separatorChars, -1, true);

3585    }

3586

3587   /**

3588    * <p>Splits the provided text into an array with a maximum length,

3589    * separators specified, preserving all tokens, including empty tokens

3590    * created by adjacent separators.</p>

3591    *

3592    * <p>The separator is not included in the returned String array.

3593    * Adjacent separators are treated as separators for empty tokens.

3594    * Adjacent separators are treated as one separator.</p>

3595    *

3596    * <p>A {@code null} input String returns {@code null}.

3597    * A {@code null} separatorChars splits on whitespace.</p>

3598    *

3599    * <p>If more than {@code max} delimited substrings are found, thelast

3600    * returned string includes all characters after the first {@code max -1}

3601    * returned strings (including separator characters).</p>

3602    *

3603    * <pre>

3604    * StringUtils.splitPreserveAllTokens(null, *, *)            = null

3605    * StringUtils.splitPreserveAllTokens("", *, *)              = []

3606    * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "cd","ef"]

3607    * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab","cd", "ef"]

3608    * StringUtils.splitPreserveAllTokens("ab:cd:ef",":", 0)    = ["ab","cd", "ef"]

3609    * StringUtils.splitPreserveAllTokens("ab:cd:ef",":", 2)    = ["ab","cd:ef"]

3610    * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab","  de fg"]

3611    * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab","", " de fg"]

3612    * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab","", "", "de fg"]

3613    * </pre>

3614    *

3615    * @param str  the String to parse,may be {@code null}

3616    * @param separatorChars  thecharacters used as the delimiters,

3617    *  {@code null} splits onwhitespace

3618    * @param max  the maximum numberof elements to include in the

3619    *  array. A zero or negative valueimplies no limit

3620    * @return an array of parsed Strings, {@code null} if null String input

3621    * @since 2.1

3622    */

3623   public static String[] splitPreserveAllTokens(final String str, finalString separatorChars, final int max) {

3624       return splitWorker(str, separatorChars, max, true);

3625   }

3626

3627   /**

3628    * Performs the logic for the {@code split} and

3629    * {@code splitPreserveAllTokens} methods that return a maximum array

3630    * length.

3631    *

3632    * @param str  the String to parse,may be {@code null}

3633    * @param separatorChars the separate character

3634    * @param max  the maximum numberof elements to include in the

3635    *  array. A zero or negative valueimplies no limit.

3636    * @param preserveAllTokens if {@code true}, adjacent separators are

3637    * treated as empty token separators; if {@code false}, adjacent

3638    * separators are treated as one separator.

3639    * @return an array of parsed Strings, {@code null} if null String input

3640    */

3641   private static String[] splitWorker(final String str, final StringseparatorChars, final int max, final boolean preserveAllTokens) {

3642       // Performance tuned for 2.0 (JDK1.4)

3643       // Direct code is quicker than StringTokenizer.

3644       // Also, StringTokenizer uses isSpace() not isWhitespace()

3645

3646       if (str == null) {

3647            return null;

3648       }

3649       final int len = str.length();

3650       if (len == 0) {

3651            returnArrayUtils.EMPTY_STRING_ARRAY;

3652       }

3653       final List<String> list = new ArrayList<>();

3654       int sizePlus1 = 1;

3655       int i = 0, start = 0;

3656       boolean match = false;

3657       boolean lastMatch = false;

3658       if (separatorChars == null) {

3659            // Null separator means usewhitespace

3660            while (i < len) {

3661                if (Character.isWhitespace(str.charAt(i))){

3662                    if (match ||preserveAllTokens) {

3663                        lastMatch = true;

3664                        if (sizePlus1++ == max){

3665                            i = len;

3666                            lastMatch = false;

3667                        }

3668                       list.add(str.substring(start, i));

3669                        match = false;

3670                    }

3671                    start = ++i;

3672                   continue;

3673                }

3674                lastMatch = false;

3675                match = true;

3676                i++;

3677            }

3678       } else if (separatorChars.length() == 1) {

3679            // Optimise 1 character case

3680            final char sep =separatorChars.charAt(0);

3681            while (i < len) {

3682                if (str.charAt(i) == sep) {

3683                    if (match ||preserveAllTokens) {

3684                        lastMatch = true;

3685                        if (sizePlus1++ == max){

3686                            i = len;

3687                            lastMatch = false;

3688                        }

3689                       list.add(str.substring(start, i));

3690                        match = false;

3691                    }

3692                    start = ++i;

3693                    continue;

3694                }

3695                lastMatch = false;

3696                match = true;

3697                i++;

3698            }

3699       } else {

3700            // standard case

3701            while (i < len) {

3702                if(separatorChars.indexOf(str.charAt(i)) >= 0) {

3703                    if (match ||preserveAllTokens) {

3704                        lastMatch = true;

3705                        if (sizePlus1++ == max){

3706                            i = len;

3707                            lastMatch = false;

3708                        }

3709                       list.add(str.substring(start, i));

3710                        match = false;

3711                    }

3712                    start = ++i;

3713                    continue;

3714                }

3715                lastMatch = false;

3716                match = true;

3717                i++;

3718            }

3719       }

3720       if (match || preserveAllTokens && lastMatch) {

3721            list.add(str.substring(start, i));

3722       }

3723       return list.toArray(new String[list.size()]);

3724   }

3725

3726    /**

3727    * <p>Splits a String by Character type as returned by

3728    * {@code java.lang.Character.getType(char)}. Groups of contiguous

3729    * characters of the same type are returned as complete tokens.

3730    * <pre>

3731    * StringUtils.splitByCharacterType(null)         = null

3732    * StringUtils.splitByCharacterType("")           = []

3733    * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ","de", " ", "fg"]

3734    * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ","fg"]

3735    * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":","cd", ":", "ef"]

3736    * StringUtils.splitByCharacterType("number5")    = ["number", "5"]

3737    * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B","ar"]

3738    * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200","B", "ar"]

3739    * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]

3740    * </pre>

3741    * @param str the String to split, may be {@code null}

3742    * @return an array of parsed Strings, {@code null} if null String input

3743    * @since 2.4

3744    */

3745   public static String[] splitByCharacterType(final String str) {

3746        return splitByCharacterType(str, false);

3747   }

3748

3749   /**

3750    * <p>Splits a String by Character type as returned by

3751    * {@code java.lang.Character.getType(char)}. Groups of contiguous

3752    * characters of the same type are returned as complete tokens, with the

3753    * following exception: the character of type

3754    * {@code Character.UPPERCASE_LETTER}, if any, immediately

3755    * preceding a token of type {@code Character.LOWERCASE_LETTER}

3756    * will belong to the following token rather than to the preceding, ifany,

3757    * {@code Character.UPPERCASE_LETTER} token.

3758    * <pre>

3759    * StringUtils.splitByCharacterTypeCamelCase(null)         = null

3760    * StringUtils.splitByCharacterTypeCamelCase("")           = []

3761    * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ","de", " ", "fg"]

3762    * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]

3763    * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":","cd", ":", "ef"]

3764    * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]

3765    * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]

3766    * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200","Bar"]

3767    * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]

3768    * </pre>

3769    * @param str the String to split, may be {@code null}

3770    * @return an array of parsed Strings, {@code null} if null String input

3771    * @since 2.4

3772    */

3773   public static String[] splitByCharacterTypeCamelCase(final String str) {

3774       return splitByCharacterType(str, true);

3775   }

3776

3777   /**

3778    * <p>Splits a String by Character type as returned by

3779    * {@code java.lang.Character.getType(char)}. Groups of contiguous

3780    * characters of the same type are returned as complete tokens, with the

3781    * following exception: if {@code camelCase} is {@code true},

3782    * the character of type {@code Character.UPPERCASE_LETTER}, if any,

3783    * immediately preceding a token of type {@codeCharacter.LOWERCASE_LETTER}

3784    * will belong to the following token rather than to the preceding, ifany,

3785    * {@code Character.UPPERCASE_LETTER} token.

3786    * @param str the String to split, may be {@code null}

3787    * @param camelCase whether to use so-called "camel-case" forletter types

3788    * @return an array of parsed Strings, {@code null} if null String input

3789    * @since 2.4

3790    */

3791   private static String[] splitByCharacterType(final String str, finalboolean camelCase) {

3792       if (str == null) {

3793            return null;

3794       }

3795       if (str.isEmpty()) {

3796            returnArrayUtils.EMPTY_STRING_ARRAY;

3797       }

3798       final char[] c = str.toCharArray();

3799       final List<String> list = new ArrayList<>();

3800       int tokenStart = 0;

3801       int currentType = Character.getType(c[tokenStart]);

3802       for (int pos = tokenStart + 1; pos < c.length; pos++) {

3803            final int type =Character.getType(c[pos]);

3804            if (type == currentType) {

3805               continue;

3806            }

3807            if (camelCase && type ==Character.LOWERCASE_LETTER && currentType ==Character.UPPERCASE_LETTER) {

3808                final int newTokenStart = pos -1;

3809                if (newTokenStart !=tokenStart) {

3810                    list.add(new String(c,tokenStart, newTokenStart - tokenStart));

3811                    tokenStart = newTokenStart;

3812                }

3813            } else {

3814                list.add(new String(c,tokenStart, pos - tokenStart));

3815                tokenStart = pos;

3816            }

3817            currentType = type;

3818       }

3819       list.add(new String(c, tokenStart, c.length - tokenStart));

3820       return list.toArray(newString[list.size()]);

3821   }

3822

3823   // Joining

3824   //-----------------------------------------------------------------------

3825   /**

3826    * <p>Joins the elements of the provided array into a single String

3827    * containing the provided list of elements.</p>

3828    *

3829    * <p>No separator is added to the joined String.

3830    * Null objects or empty strings within the array are represented by

3831    * empty strings.</p>

3832    *

3833    * <pre>

3834    * StringUtils.join(null)           = null

3835    * StringUtils.join([])             = ""

3836    * StringUtils.join([null])         = ""

3837    * StringUtils.join(["a", "b", "c"]) ="abc"

3838    * StringUtils.join([null, "", "a"]) = "a"

3839    * </pre>

3840    *

3841    * @param <T> the specific type of values to join together

3842    * @param elements  the values tojoin together, may be null

3843    * @return the joined String, {@code null} if null array input

3844    * @since 2.0

3845    * @since 3.0 Changed signature to use varargs

3846    */

3847   @SafeVarargs

3848   public static <T> String join(final T... elements) {

3849       return join(elements, null);

3850   }

3851

3852   /**

3853    * <p>Joins the elements of the provided array into a single String

3854    * containing the provided list of elements.</p>

3855    *

3856    * <p>No delimiter is added before or after the list.

3857    * Null objects or empty strings within the array are represented by

3858    * empty strings.</p>

3859    *

3860    * <pre>

3861    * StringUtils.join(null, *)              = null

3862    * StringUtils.join([], *)                = ""

3863    * StringUtils.join([null], *)            = ""

3864    * StringUtils.join(["a", "b", "c"],';')  = "a;b;c"

3865    * StringUtils.join(["a", "b", "c"], null)= "abc"

3866    * StringUtils.join([null, "", "a"], ';')  = ";;a"

3867    * </pre>

3868    *

3869    * @param array  the array ofvalues to join together, may be null

3870    * @param separator  the separatorcharacter to use

3871    * @return the joined String, {@code null} if null array input

3872    * @since 2.0

3873    */

3874   public static String join(final Object[] array, final char separator) {

3875       if (array == null) {

3876            return null;

3877       }

3878       return join(array, separator, 0, array.length);

3879   }

3880

3881   /**

3882    * <p>

3883    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

3884    * </p>

3885    *

3886    * <p>

3887    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

3888    * by empty strings.

3889    * </p>

3890    *

3891    * <pre>

3892    * StringUtils.join(null, *)              = null

3893    * StringUtils.join([], *)                = ""

3894    * StringUtils.join([null], *)            = ""

3895    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

3896    * StringUtils.join([1, 2, 3], null) = "123"

3897    * </pre>

3898    *

3899    * @param array

3900    *            the array of values tojoin together, may be null

3901    * @param separator

3902    *            the separatorcharacter to use

3903    * @return the joined String, {@code null} if null array input

3904    * @since 3.2

3905    */

3906   public static String join(final long[] array, final char separator) {

3907       if (array == null) {

3908            return null;

3909       }

3910       return join(array, separator, 0, array.length);

3911   }

3912

3913   /**

3914    * <p>

3915    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

3916    * </p>

3917    *

3918    * <p>

3919    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

3920    * by empty strings.

3921    * </p>

3922    *

3923    * <pre>

3924    * StringUtils.join(null, *)              = null

3925    * StringUtils.join([], *)                = ""

3926    * StringUtils.join([null], *)            = ""

3927    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

3928    * StringUtils.join([1, 2, 3], null) = "123"

3929    * </pre>

3930    *

3931    * @param array

3932    *            the array of valuesto join together, may be null

3933    * @param separator

3934    *            the separatorcharacter to use

3935    * @return the joined String, {@code null} if null array input

3936    * @since 3.2

3937    */

3938   public static String join(final int[] array, final char separator) {

3939       if (array == null) {

3940            return null;

3941       }

3942       return join(array, separator, 0, array.length);

3943   }

3944

3945   /**

3946    * <p>

3947     * Joins the elements of the provided arrayinto a single String containing the provided list of elements.

3948    * </p>

3949    *

3950    * <p>

3951    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

3952    * by empty strings.

3953    * </p>

3954    *

3955    * <pre>

3956    * StringUtils.join(null, *)              = null

3957    * StringUtils.join([], *)                = ""

3958    * StringUtils.join([null], *)            = ""

3959    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

3960    * StringUtils.join([1, 2, 3], null) = "123"

3961    * </pre>

3962    *

3963    * @param array

3964    *            the array of values tojoin together, may be null

3965    * @param separator

3966    *            the separatorcharacter to use

3967    * @return the joined String, {@code null} if null array input

3968    * @since 3.2

3969    */

3970   public static String join(final short[] array, final char separator) {

3971       if (array == null) {

3972            return null;

3973       }

3974       return join(array, separator, 0, array.length);

3975   }

3976

3977   /**

3978    * <p>

3979    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

3980    * </p>

3981    *

3982    * <p>

3983    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

3984    * by empty strings.

3985    * </p>

3986    *

3987    * <pre>

3988    * StringUtils.join(null, *)              = null

3989    * StringUtils.join([], *)                = ""

3990    * StringUtils.join([null], *)            = ""

3991    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

3992    * StringUtils.join([1, 2, 3], null) = "123"

3993    * </pre>

3994    *

3995    * @param array

3996    *            the array of valuesto join together, may be null

3997    * @param separator

3998    *            the separatorcharacter to use

3999    * @return the joined String, {@code null} if null array input

4000    * @since 3.2

4001    */

4002   public static String join(final byte[] array, final char separator) {

4003       if (array == null) {

4004            return null;

4005       }

4006       return join(array, separator, 0, array.length);

4007   }

4008

4009   /**

4010    * <p>

4011    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4012    * </p>

4013    *

4014    * <p>

4015    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4016    * by empty strings.

4017    * </p>

4018    *

4019    * <pre>

4020    * StringUtils.join(null, *)              = null

4021    * StringUtils.join([], *)                = ""

4022    * StringUtils.join([null], *)            = ""

4023    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4024    * StringUtils.join([1, 2, 3], null) = "123"

4025    * </pre>

4026    *

4027    * @param array

4028    *            the array of valuesto join together, may be null

4029    * @param separator

4030    *            the separatorcharacter to use

4031    * @return the joined String, {@code null} if null array input

4032    * @since 3.2

4033    */

4034   public static String join(final char[] array, final char separator) {

4035       if (array == null) {

4036            return null;

4037       }

4038       return join(array, separator, 0, array.length);

4039   }

4040

4041   /**

4042    * <p>

4043    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4044    * </p>

4045    *

4046    * <p>

4047    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4048    * by empty strings.

4049    * </p>

4050    *

4051    * <pre>

4052    * StringUtils.join(null, *)              = null

4053    * StringUtils.join([], *)                = ""

4054    * StringUtils.join([null], *)            = ""

4055    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4056    * StringUtils.join([1, 2, 3], null) = "123"

4057    * </pre>

4058    *

4059    * @param array

4060    *            the array of valuesto join together, may be null

4061    * @param separator

4062    *            the separatorcharacter to use

4063    * @return the joined String, {@code null} if null array input

4064    * @since 3.2

4065    */

4066   public static String join(final float[] array, final char separator) {

4067       if (array == null) {

4068            return null;

4069       }

4070       return join(array, separator, 0, array.length);

4071   }

4072

4073   /**

4074    * <p>

4075    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4076    * </p>

4077    *

4078    * <p>

4079    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4080    * by empty strings.

4081    * </p>

4082    *

4083    * <pre>

4084    * StringUtils.join(null, *)              = null

4085    * StringUtils.join([], *)                = ""

4086    * StringUtils.join([null], *)            = ""

4087    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4088    * StringUtils.join([1, 2, 3], null) = "123"

4089    * </pre>

4090    *

4091    * @param array

4092    *            the array of valuesto join together, may be null

4093    * @param separator

4094    *            the separatorcharacter to use

4095    * @return the joined String, {@code null} if null array input

4096    * @since 3.2

4097    */

4098   public static String join(final double[] array, final char separator) {

4099       if (array == null) {

4100            return null;

4101       }

4102       return join(array, separator, 0, array.length);

4103   }

4104

4105

4106   /**

4107    * <p>Joins the elements of the provided array into a single String

4108    * containing the provided list of elements.</p>

4109    *

4110    * <p>No delimiter is added before or after the list.

4111    * Null objects or empty strings within the array are represented by

4112    * empty strings.</p>

4113    *

4114    * <pre>

4115    * StringUtils.join(null, *)              = null

4116    * StringUtils.join([], *)                = ""

4117    * StringUtils.join([null], *)            = ""

4118    * StringUtils.join(["a", "b", "c"],';')  = "a;b;c"

4119    * StringUtils.join(["a", "b", "c"], null)= "abc"

4120    * StringUtils.join([null, "", "a"], ';')  = ";;a"

4121    * </pre>

4122    *

4123    * @param array  the array ofvalues to join together, may be null

4124    * @param separator  the separatorcharacter to use

4125    * @param startIndex the first index to start joining from.  It is

4126    * an error to pass in an end index past the end of the array

4127    * @param endIndex the index to stop joining from (exclusive). It is

4128    * an error to pass in an end index past the end of the array

4129    * @return the joined String, {@code null} if null array input

4130    * @since 2.0

4131    */

4132   public static String join(final Object[] array, final char separator,final int startIndex, final int endIndex) {

4133       if (array == null) {

4134            return null;

4135       }

4136       final int noOfItems = endIndex - startIndex;

4137       if (noOfItems <= 0) {

4138            return EMPTY;

4139       }

4140       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4141       for (int i = startIndex; i < endIndex; i++) {

4142            if (i > startIndex) {

4143                buf.append(separator);

4144            }

4145            if (array[i] != null) {

4146                buf.append(array[i]);

4147            }

4148       }

4149       return buf.toString();

4150   }

4151

4152   /**

4153    * <p>

4154    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4155    * </p>

4156    *

4157    * <p>

4158    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4159    * by empty strings.

4160    * </p>

4161    *

4162    * <pre>

4163    * StringUtils.join(null, *)              = null

4164    * StringUtils.join([], *)                = ""

4165    * StringUtils.join([null], *)            = ""

4166    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4167    * StringUtils.join([1, 2, 3], null) = "123"

4168    * </pre>

4169    *

4170    * @param array

4171    *            the array of valuesto join together, may be null

4172    * @param separator

4173    *            the separatorcharacter to use

4174    * @param startIndex

4175    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4176    *            array

4177    * @param endIndex

4178    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4179    *            the array

4180    * @return the joined String, {@code null} if null array input

4181    * @since 3.2

4182    */

4183   public static String join(final long[] array, final char separator,final int startIndex, final int endIndex) {

4184       if (array == null) {

4185            return null;

4186       }

4187       final int noOfItems = endIndex - startIndex;

4188       if (noOfItems <= 0) {

4189            return EMPTY;

4190       }

4191       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4192       for (int i = startIndex; i < endIndex; i++) {

4193            if (i > startIndex) {

4194                buf.append(separator);

4195            }

4196            buf.append(array[i]);

4197       }

4198       return buf.toString();

4199   }

4200

4201   /**

4202    * <p>

4203    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4204    * </p>

4205    *

4206    * <p>

4207    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4208    * by empty strings.

4209    * </p>

4210    *

4211    * <pre>

4212    * StringUtils.join(null, *)              = null

4213    * StringUtils.join([], *)                = ""

4214    * StringUtils.join([null], *)            = ""

4215    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4216    * StringUtils.join([1, 2, 3], null) = "123"

4217    * </pre>

4218    *

4219    * @param array

4220    *            the array of valuesto join together, may be null

4221    * @param separator

4222    *            the separatorcharacter to use

4223    * @param startIndex

4224    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4225    *            array

4226    * @param endIndex

4227    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4228    *            the array

4229    * @return the joined String, {@code null} if null array input

4230    * @since 3.2

4231    */

4232   public static String join(final int[] array, final char separator, finalint startIndex, final int endIndex) {

4233       if (array == null) {

4234            return null;

4235       }

4236       final int noOfItems = endIndex - startIndex;

4237        if (noOfItems <= 0) {

4238            return EMPTY;

4239       }

4240       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4241       for (int i = startIndex; i < endIndex; i++) {

4242            if (i > startIndex) {

4243                buf.append(separator);

4244            }

4245            buf.append(array[i]);

4246       }

4247       return buf.toString();

4248   }

4249

4250   /**

4251    * <p>

4252    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4253    * </p>

4254    *

4255    * <p>

4256    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4257    * by empty strings.

4258    * </p>

4259    *

4260    * <pre>

4261    * StringUtils.join(null, *)              = null

4262    * StringUtils.join([], *)                = ""

4263    * StringUtils.join([null], *)            = ""

4264    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4265    * StringUtils.join([1, 2, 3], null) = "123"

4266    * </pre>

4267    *

4268    * @param array

4269    *            the array of valuesto join together, may be null

4270    * @param separator

4271    *            the separatorcharacter to use

4272    * @param startIndex

4273    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4274    *            array

4275    * @param endIndex

4276    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4277    *            the array

4278    * @return the joined String, {@code null} if null array input

4279    * @since 3.2

4280    */

4281   public static String join(final byte[] array, final char separator,final int startIndex, final int endIndex) {

4282       if (array == null) {

4283            return null;

4284       }

4285       final int noOfItems = endIndex - startIndex;

4286       if (noOfItems <= 0) {

4287            return EMPTY;

4288       }

4289       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4290       for (int i = startIndex; i < endIndex; i++) {

4291            if (i > startIndex) {

4292                buf.append(separator);

4293            }

4294            buf.append(array[i]);

4295       }

4296       return buf.toString();

4297   }

4298

4299   /**

4300    * <p>

4301    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4302    * </p>

4303    *

4304    * <p>

4305    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4306    * by empty strings.

4307    * </p>

4308    *

4309    * <pre>

4310    * StringUtils.join(null, *)              = null

4311    * StringUtils.join([], *)                = ""

4312    * StringUtils.join([null], *)            = ""

4313    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4314    * StringUtils.join([1, 2, 3], null) = "123"

4315    * </pre>

4316    *

4317    * @param array

4318    *            the array of valuesto join together, may be null

4319    * @param separator

4320    *            the separatorcharacter to use

4321    * @param startIndex

4322    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4323    *            array

4324    * @param endIndex

4325    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4326    *            the array

4327    * @return the joined String, {@code null} if null array input

4328    * @since 3.2

4329    */

4330   public static String join(final short[] array, final char separator,final int startIndex, final int endIndex) {

4331       if (array == null) {

4332            return null;

4333       }

4334       final int noOfItems = endIndex - startIndex;

4335       if (noOfItems <= 0) {

4336            return EMPTY;

4337       }

4338       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4339       for (int i = startIndex; i < endIndex; i++) {

4340            if (i > startIndex) {

4341                buf.append(separator);

4342            }

4343            buf.append(array[i]);

4344       }

4345       return buf.toString();

4346   }

4347

4348   /**

4349    * <p>

4350    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4351    * </p>

4352    *

4353    * <p>

4354    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4355    * by empty strings.

4356    * </p>

4357    *

4358    * <pre>

4359    * StringUtils.join(null, *)              = null

4360    * StringUtils.join([], *)                = ""

4361    * StringUtils.join([null], *)            = ""

4362    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4363    * StringUtils.join([1, 2, 3], null) = "123"

4364    * </pre>

4365    *

4366    * @param array

4367    *            the array of valuesto join together, may be null

4368    * @param separator

4369    *            the separatorcharacter to use

4370    * @param startIndex

4371    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4372    *            array

4373    * @param endIndex

4374    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4375    *            the array

4376    * @return the joined String, {@code null} if null array input

4377    * @since 3.2

4378    */

4379   public static String join(final char[] array, final char separator,final int startIndex, final int endIndex) {

4380       if (array == null) {

4381            return null;

4382       }

4383       final int noOfItems = endIndex - startIndex;

4384       if (noOfItems <= 0) {

4385            return EMPTY;

4386       }

4387       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4388       for (int i = startIndex; i < endIndex; i++) {

4389            if (i > startIndex) {

4390                buf.append(separator);

4391            }

4392            buf.append(array[i]);

4393       }

4394       return buf.toString();

4395   }

4396

4397   /**

4398    * <p>

4399    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4400    * </p>

4401    *

4402    * <p>

4403    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4404    * by empty strings.

4405    * </p>

4406    *

4407    * <pre>

4408    * StringUtils.join(null, *)              = null

4409    * StringUtils.join([], *)                = ""

4410    * StringUtils.join([null], *)            = ""

4411    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4412    * StringUtils.join([1, 2, 3], null) = "123"

4413    * </pre>

4414    *

4415    * @param array

4416    *            the array of valuesto join together, may be null

4417    * @param separator

4418    *            the separatorcharacter to use

4419    * @param startIndex

4420    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4421    *            array

4422    * @param endIndex

4423    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4424    *            the array

4425    * @return the joined String, {@code null} if null array input

4426    * @since 3.2

4427    */

4428   public static String join(final double[] array, final char separator,final int startIndex, final int endIndex) {

4429       if (array == null) {

4430            return null;

4431       }

4432       final int noOfItems = endIndex - startIndex;

4433       if (noOfItems <= 0) {

4434            return EMPTY;

4435       }

4436       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4437       for (int i = startIndex; i < endIndex; i++) {

4438            if (i > startIndex) {

4439                buf.append(separator);

4440            }

4441            buf.append(array[i]);

4442       }

4443       return buf.toString();

4444   }

4445

4446   /**

4447    * <p>

4448    * Joins the elements of the provided array into a single Stringcontaining the provided list of elements.

4449    * </p>

4450    *

4451    * <p>

4452    * No delimiter is added before or after the list. Null objects or emptystrings within the array are represented

4453    * by empty strings.

4454    * </p>

4455    *

4456    * <pre>

4457    * StringUtils.join(null, *)              = null

4458    * StringUtils.join([], *)                = ""

4459    * StringUtils.join([null], *)            = ""

4460    * StringUtils.join([1, 2, 3], ';') = "1;2;3"

4461    * StringUtils.join([1, 2, 3], null) = "123"

4462    * </pre>

4463    *

4464    * @param array

4465    *            the array of valuesto join together, may be null

4466    * @param separator

4467    *            the separatorcharacter to use

4468    * @param startIndex

4469    *            the first index tostart joining from. It is an error to pass in an end index past the end of the

4470    *            array

4471    * @param endIndex

4472    *            the index to stopjoining from (exclusive). It is an error to pass in an end index past the endof

4473    *            the array

4474    * @return the joined String, {@code null} if null array input

4475    * @since 3.2

4476    */

4477   public static String join(final float[] array, final char separator,final int startIndex, final int endIndex) {

4478       if (array == null) {

4479            return null;

4480       }

4481       final int noOfItems = endIndex - startIndex;

4482       if (noOfItems <= 0) {

4483            return EMPTY;

4484       }

4485       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4486       for (int i = startIndex; i < endIndex; i++) {

4487            if (i > startIndex) {

4488                buf.append(separator);

4489            }

4490            buf.append(array[i]);

4491       }

4492       return buf.toString();

4493   }

4494

4495

4496   /**

4497    * <p>Joins the elements of the provided array into a single String

4498    * containing the provided list of elements.</p>

4499    *

4500    * <p>No delimiter is added before or after the list.

4501    * A {@code null} separator is the same as an empty String("").

4502    * Null objects or empty strings within the array are represented by

4503    * empty strings.</p>

4504    *

4505    * <pre>

4506    * StringUtils.join(null, *)                = null

4507    * StringUtils.join([], *)                  = ""

4508    * StringUtils.join([null], *)              = ""

4509    * StringUtils.join(["a", "b", "c"],"--")  = "a--b--c"

4510    * StringUtils.join(["a", "b", "c"],null)  = "abc"

4511    * StringUtils.join(["a", "b", "c"],"")    = "abc"

4512    * StringUtils.join([null, "", "a"], ',')   = ",,a"

4513    * </pre>

4514    *

4515    * @param array  the array ofvalues to join together, may be null

4516    * @param separator  the separatorcharacter to use, null treated as ""

4517    * @return the joined String, {@code null} if null array input

4518    */

4519   public static String join(final Object[] array, final String separator){

4520       if (array == null) {

4521            return null;

4522       }

4523       return join(array, separator, 0, array.length);

4524   }

4525

4526   /**

4527    * <p>Joins the elements of the provided array into a single String

4528    * containing the provided list of elements.</p>

4529    *

4530    * <p>No delimiter is added before or after the list.

4531    * A {@code null} separator is the same as an empty String("").

4532    * Null objects or empty strings within the array are represented by

4533    * empty strings.</p>

4534    *

4535    * <pre>

4536    * StringUtils.join(null, *, *, *)                = null

4537    * StringUtils.join([], *, *, *)                  = ""

4538    * StringUtils.join([null], *, *, *)              = ""

4539    * StringUtils.join(["a", "b", "c"],"--", 0, 3)  ="a--b--c"

4540    * StringUtils.join(["a", "b", "c"],"--", 1, 3)  = "b--c"

4541    * StringUtils.join(["a", "b", "c"],"--", 2, 3)  = "c"

4542    * StringUtils.join(["a", "b", "c"],"--", 2, 2)  = ""

4543    * StringUtils.join(["a", "b", "c"], null,0, 3)  = "abc"

4544    * StringUtils.join(["a", "b", "c"],"", 0, 3)    = "abc"

4545    * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"

4546    * </pre>

4547    *

4548    * @param array  the array ofvalues to join together, may be null

4549    * @param separator  the separatorcharacter to use, null treated as ""

4550    * @param startIndex the first index to start joining from.

4551    * @param endIndex the index to stop joining from (exclusive).

4552    * @return the joined String, {@code null} if null array input; or theempty string

4553    * if {@code endIndex - startIndex <= 0}. The number of joined entriesis given by

4554    * {@code endIndex - startIndex}

4555    * @throws ArrayIndexOutOfBoundsException ife<br>

4556    * {@code startIndex < 0} or <br>

4557    * {@code startIndex >= array.length()} or <br>

4558    * {@code endIndex < 0} or <br>

4559    * {@code endIndex > array.length()}

4560    */

4561   public static String join(final Object[] array, String separator, finalint startIndex, final int endIndex) {

4562       if (array == null) {

4563            return null;

4564       }

4565       if (separator == null) {

4566            separator = EMPTY;

4567       }

4568

4569       // endIndex - startIndex > 0:  Len = NofStrings *(len(firstString) + len(separator))

4570       //           (Assuming that allStrings are roughly equally long)

4571       final int noOfItems = endIndex - startIndex;

4572       if (noOfItems <= 0) {

4573            return EMPTY;

4574       }

4575

4576       final StringBuilder buf = new StringBuilder(noOfItems * 16);

4577

4578       for (int i = startIndex; i < endIndex; i++) {

4579            if (i > startIndex) {

4580                buf.append(separator);

4581            }

4582            if (array[i] != null) {

4583                buf.append(array[i]);

4584            }

4585       }

4586       return buf.toString();

4587   }

4588

4589   /**

4590    * <p>Joins the elements of the provided {@code Iterator} into

4591    * a single String containing the provided elements.</p>

4592    *

4593    * <p>No delimiter is added before or after the list. Null objectsor empty

4594    * strings within the iteration are represented by emptystrings.</p>

4595    *

4596    * <p>See the examples here: {@link #join(Object[],char)}.</p>

4597    *

4598    * @param iterator  the {@codeIterator} of values to join together, may be null

4599    * @param separator  the separatorcharacter to use

4600    * @return the joined String, {@code null} if null iterator input

4601    * @since 2.0

4602    */

4603   public static String join(final Iterator<?> iterator, final charseparator) {

4604

4605       // handle null, zero and one elements before building a buffer

4606       if (iterator == null) {

4607            return null;

4608       }

4609       if (!iterator.hasNext()) {

4610            return EMPTY;

4611       }

4612       final Object first = iterator.next();

4613       if (!iterator.hasNext()) {

4614           final String result =Objects.toString(first, "");

4615            return result;

4616       }

4617

4618       // two or more elements

4619       final StringBuilder buf = new StringBuilder(256); // Java default is 16,probably too small

4620       if (first != null) {

4621            buf.append(first);

4622       }

4623

4624       while (iterator.hasNext()) {

4625            buf.append(separator);

4626            final Object obj = iterator.next();

4627            if (obj != null) {

4628                buf.append(obj);

4629            }

4630       }

4631

4632       return buf.toString();

4633   }

4634

4635   /**

4636    * <p>Joins the elements of the provided {@code Iterator} into

4637    * a single String containing the provided elements.</p>

4638    *

4639    * <p>No delimiter is added before or after the list.

4640    * A {@code null} separator is the same as an empty String("").</p>

4641    *

4642    * <p>See the examples here: {@link #join(Object[],String)}.</p>

4643    *

4644    * @param iterator  the {@codeIterator} of values to join together, may be null

4645    * @param separator  the separatorcharacter to use, null treated as ""

4646    * @return the joined String, {@code null} if null iterator input

4647    */

4648   public static String join(final Iterator<?> iterator, final Stringseparator) {

4649

4650       // handle null, zero and one elements before building a buffer

4651       if (iterator == null) {

4652            return null;

4653       }

4654       if (!iterator.hasNext()) {

4655            return EMPTY;

4656       }

4657       final Object first = iterator.next();

4658       if (!iterator.hasNext()) {

4659            final String result = Objects.toString(first,"");

4660            return result;

4661       }

4662

4663       // two or more elements

4664       final StringBuilder buf = new StringBuilder(256); // Java default is 16,probably too small

4665       if (first != null) {

4666           buf.append(first);

4667       }

4668

4669       while (iterator.hasNext()) {

4670            if (separator != null) {

4671                buf.append(separator);

4672            }

4673            final Object obj = iterator.next();

4674            if (obj != null) {

4675                buf.append(obj);

4676            }

4677       }

4678       return buf.toString();

4679   }

4680

4681   /**

4682    * <p>Joins the elements of the provided {@code Iterable} into

4683    * a single String containing the provided elements.</p>

4684    *

4685    * <p>No delimiter is added before or after the list. Null objectsor empty

4686    * strings within the iteration are represented by emptystrings.</p>

4687    *

4688    * <p>See the examples here: {@link #join(Object[],char)}.</p>

4689    *

4690    * @param iterable  the {@codeIterable} providing the values to join together, may be null

4691    * @param separator  the separatorcharacter to use

4692    * @return the joined String, {@code null} if null iterator input

4693    * @since 2.3

4694    */

4695   public static String join(final Iterable<?> iterable, final charseparator) {

4696       if (iterable == null) {

4697            return null;

4698       }

4699       return join(iterable.iterator(), separator);

4700   }

4701

4702   /**

4703    * <p>Joins the elements of the provided {@code Iterable} into

4704    * a single String containing the provided elements.</p>

4705    *

4706    * <p>No delimiter is added before or after the list.

4707    * A {@code null} separator is the same as an empty String("").</p>

4708    *

4709    * <p>See the examples here: {@link #join(Object[],String)}.</p>

4710    *

4711    * @param iterable  the {@codeIterable} providing the values to join together, may be null

4712    * @param separator  the separatorcharacter to use, null treated as ""

4713    * @return the joined String, {@code null} if null iterator input

4714    * @since 2.3

4715    */

4716   public static String join(final Iterable<?> iterable, final Stringseparator) {

4717       if (iterable == null) {

4718            return null;

4719       }

4720       return join(iterable.iterator(), separator);

4721   }

4722

4723   /**

4724    * <p>Joins the elements of the provided varargs into a

4725    * single String containing the provided elements.</p>

4726    *

4727    * <p>No delimiter is added before or after the list.

4728    * {@code null} elements and separator are treated as empty Strings("").</p>

4729    *

4730    * <pre>

4731    * StringUtils.joinWith(",", {"a","b"})        = "a,b"

4732    * StringUtils.joinWith(",", {"a","b",""})     ="a,b,"

4733    * StringUtils.joinWith(",", {"a", null,"b"})  = "a,,b"

4734    * StringUtils.joinWith(null,{"a", "b"})       ="ab"

4735    * </pre>

4736    *

4737    * @param separator the separator character to use, null treated as""

4738    * @param objects the varargs providing the values to join together.{@code null} elements are treated as ""

4739    * @return the joined String.

4740    * @throws java.lang.IllegalArgumentException if a null varargs isprovided

4741    * @since 3.5

4742    */

4743   public static String joinWith(final String separator, final Object...objects) {

4744       if (objects == null) {

4745            throw newIllegalArgumentException("Object varargs must not be null");

4746       }

4747

4748       final String sanitizedSeparator = defaultString(separator,StringUtils.EMPTY);

4749

4750       final StringBuilder result = new StringBuilder();

4751

4752       final Iterator<Object> iterator =Arrays.asList(objects).iterator();

4753       while (iterator.hasNext()) {

4754            final String value =Objects.toString(iterator.next(), "");

4755            result.append(value);

4756

4757            if (iterator.hasNext()) {

4758               result.append(sanitizedSeparator);

4759            }

4760       }

4761

4762       return result.toString();

4763   }

4764

4765   // Delete

4766   //-----------------------------------------------------------------------

4767   /**

4768    * <p>Deletes all whitespaces from a String as defined by

4769    * {@link Character#isWhitespace(char)}.</p>

4770    *

4771    * <pre>

4772    * StringUtils.deleteWhitespace(null)         = null

4773    * StringUtils.deleteWhitespace("")           = ""

4774    * StringUtils.deleteWhitespace("abc")        = "abc"

4775    * StringUtils.deleteWhitespace("  ab  c  ") = "abc"

4776    * </pre>

4777    *

4778    * @param str  the String to deletewhitespace from, may be null

4779    * @return the String without whitespaces, {@code null} if null Stringinput

4780    */

4781   public static String deleteWhitespace(final String str) {

4782       if (isEmpty(str)) {

4783            return str;

4784       }

4785       final int sz = str.length();

4786       final char[] chs = new char[sz];

4787       int count = 0;

4788       for (int i = 0; i < sz; i++) {

4789            if(!Character.isWhitespace(str.charAt(i))) {

4790                chs[count++] = str.charAt(i);

4791            }

4792       }

4793       if (count == sz) {

4794            return str;

4795       }

4796       return new String(chs, 0, count);

4797   }

4798

4799   // Remove

4800   //-----------------------------------------------------------------------

4801   /**

4802    * <p>Removes a substring only if it is at the beginning of a sourcestring,

4803    * otherwise returns the source string.</p>

4804    *

4805    * <p>A {@code null} source string will return {@code null}.

4806    * An empty ("") source string will return the empty string.

4807    * A {@code null} search string will return the source string.</p>

4808    *

4809    * <pre>

4810    * StringUtils.removeStart(null, *)     = null

4811    * StringUtils.removeStart("", *)        = ""

4812    * StringUtils.removeStart(*, null)     = *

4813    * StringUtils.removeStart("www.domain.com","www.")   ="domain.com"

4814    * StringUtils.removeStart("domain.com", "www.")       = "domain.com"

4815    * StringUtils.removeStart("www.domain.com","domain") = "www.domain.com"

4816    * StringUtils.removeStart("abc", "")    = "abc"

4817    * </pre>

4818    *

4819    * @param str  the source String tosearch, may be null

4820    * @param remove  the String tosearch for and remove, may be null

4821    * @return the substring with the string removed if found,

4822    *  {@code null} if null Stringinput

4823    * @since 2.1

4824    */

4825   public static String removeStart(final String str, final String remove){

4826       if (isEmpty(str) || isEmpty(remove)) {

4827            return str;

4828       }

4829        if (str.startsWith(remove)){

4830            returnstr.substring(remove.length());

4831       }

4832       return str;

4833   }

4834

4835   /**

4836    * <p>Case insensitive removal of a substring if it is at thebeginning of a source string,

4837    * otherwise returns the source string.</p>

4838    *

4839    * <p>A {@code null} source string will return {@code null}.

4840    * An empty ("") source string will return the empty string.

4841    * A {@code null} search string will return the source string.</p>

4842    *

4843    * <pre>

4844    * StringUtils.removeStartIgnoreCase(null, *)      = null

4845    * StringUtils.removeStartIgnoreCase("", *)        = ""

4846    * StringUtils.removeStartIgnoreCase(*, null)      = *

4847    * StringUtils.removeStartIgnoreCase("www.domain.com","www.")   ="domain.com"

4848    * StringUtils.removeStartIgnoreCase("www.domain.com","WWW.")   ="domain.com"

4849    * StringUtils.removeStartIgnoreCase("domain.com","www.")       ="domain.com"

4850    * StringUtils.removeStartIgnoreCase("www.domain.com","domain") = "www.domain.com"

4851    * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"

4852    * </pre>

4853    *

4854    * @param str  the source String tosearch, may be null

4855    * @param remove  the String tosearch for (case insensitive) and remove, may be null

4856    * @return the substring with the string removed if found,

4857    *  {@code null} if null Stringinput

4858    * @since 2.4

4859    */

4860   public static String removeStartIgnoreCase(final String str, finalString remove) {

4861       if (isEmpty(str) || isEmpty(remove)) {

4862            return str;

4863       }

4864       if (startsWithIgnoreCase(str, remove)) {

4865            returnstr.substring(remove.length());

4866       }

4867       return str;

4868   }

4869

4870   /**

4871    * <p>Removes a substring only if it is at the end of a sourcestring,

4872    * otherwise returns the source string.</p>

4873    *

4874    * <p>A {@code null} source string will return {@code null}.

4875    * An empty ("") source string will return the empty string.

4876    * A {@code null} search string will return the source string.</p>

4877    *

4878    * <pre>

4879    * StringUtils.removeEnd(null, *)     = null

4880    * StringUtils.removeEnd("", *)        = ""

4881    * StringUtils.removeEnd(*, null)     = *

4882    * StringUtils.removeEnd("www.domain.com",".com.")  ="www.domain.com"

4883    * StringUtils.removeEnd("www.domain.com",".com")   ="www.domain"

4884    * StringUtils.removeEnd("www.domain.com", "domain")= "www.domain.com"

4885    * StringUtils.removeEnd("abc", "")    = "abc"

4886    * </pre>

4887    *

4888    * @param str  the source String tosearch, may be null

4889    * @param remove  the String tosearch for and remove, may be null

4890    * @return the substring with the string removed if found,

4891    *  {@code null} if null Stringinput

4892    * @since 2.1

4893    */

4894   public static String removeEnd(final String str, final String remove) {

4895       if (isEmpty(str) || isEmpty(remove)) {

4896            return str;

4897       }

4898       if (str.endsWith(remove)) {

4899            return str.substring(0, str.length()- remove.length());

4900       }

4901       return str;

4902   }

4903

4904   /**

4905    * <p>Case insensitive removal of a substring if it is at the endof a source string,

4906    * otherwise returns the source string.</p>

4907    *

4908    * <p>A {@code null} sourcestring will return {@code null}.

4909    * An empty ("") source string will return the empty string.

4910    * A {@code null} search string will return the source string.</p>

4911    *

4912    * <pre>

4913    * StringUtils.removeEndIgnoreCase(null, *)      = null

4914    * StringUtils.removeEndIgnoreCase("", *)        = ""

4915    * StringUtils.removeEndIgnoreCase(*, null)      = *

4916    * StringUtils.removeEndIgnoreCase("www.domain.com",".com.")  = "www.domain.com"

4917    * StringUtils.removeEndIgnoreCase("www.domain.com",".com")   ="www.domain"

4918    * StringUtils.removeEndIgnoreCase("www.domain.com","domain") = "www.domain.com"

4919    * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"

4920    * StringUtils.removeEndIgnoreCase("www.domain.com",".COM") = "www.domain")

4921    * StringUtils.removeEndIgnoreCase("www.domain.COM",".com") = "www.domain")

4922    * </pre>

4923    *

4924    * @param str  the source String tosearch, may be null

4925    * @param remove  the String tosearch for (case insensitive) and remove, may be null

4926    * @return the substring with the string removed if found,

4927    *  {@code null} if null Stringinput

4928    * @since 2.4

4929    */

4930   public static String removeEndIgnoreCase(final String str, final Stringremove) {

4931       if (isEmpty(str) || isEmpty(remove)) {

4932            return str;

4933       }

4934       if (endsWithIgnoreCase(str, remove)) {

4935            return str.substring(0,str.length() - remove.length());

4936       }

4937       return str;

4938   }

4939

4940   /**

4941    * <p>Removes all occurrences of a substring from within the sourcestring.</p>

4942    *

4943    * <p>A {@code null} source string will return {@code null}.

4944    * An empty ("") source string will return the empty string.

4945    * A {@code null} remove string will return the source string.

4946    * An empty ("") remove string will return the sourcestring.</p>

4947    *

4948    * <pre>

4949    * StringUtils.remove(null, *)       = null

4950    * StringUtils.remove("", *)          = ""

4951    * StringUtils.remove(*, null)       = *

4952    * StringUtils.remove(*, "")          = *

4953    * StringUtils.remove("queued", "ue") ="qd"

4954    * StringUtils.remove("queued", "zz") ="queued"

4955    * </pre>

4956    *

4957    * @param str  the source String tosearch, may be null

4958    * @param remove  the String tosearch for and remove, may be null

4959    * @return the substring with the string removed if found,

4960    *  {@code null} if null Stringinput

4961    * @since 2.1

4962    */

4963   public static String remove(final String str, final String remove) {

4964       if (isEmpty(str) || isEmpty(remove)) {

4965            return str;

4966       }

4967       return replace(str, remove, EMPTY, -1);

4968   }

4969

4970   /**

4971    * <p>

4972    * Case insensitive removal of all occurrences of a substring from within

4973    * the source string.

4974    * </p>

4975    *

4976    * <p>

4977    * A {@code null} source string will return {@code null}. An empty("")

4978    * source string will return the empty string. A {@code null} removestring

4979    * will return the source string. An empty ("") remove stringwill return

4980    * the source string.

4981    * </p>

4982    *

4983    * <pre>

4984    * StringUtils.removeIgnoreCase(null, *)        = null

4985    * StringUtils.removeIgnoreCase("", *)          = ""

4986    * StringUtils.removeIgnoreCase(*, null)        = *

4987    * StringUtils.removeIgnoreCase(*, "")          = *

4988    * StringUtils.removeIgnoreCase("queued", "ue") ="qd"

4989    * StringUtils.removeIgnoreCase("queued", "zz") ="queued"

4990    * StringUtils.removeIgnoreCase("quEUed", "UE") ="qd"

4991    * StringUtils.removeIgnoreCase("queued", "zZ") ="queued"

4992    * </pre>

4993    *

4994    * @param str

4995    *            the source String tosearch, may be null

4996    * @param remove

4997    *            the String to searchfor (case insensitive) and remove, may be

4998    *            null

4999     * @return the substring with the stringremoved if found, {@code null} if

5000    *         null String input

5001    * @since 3.5

5002    */

5003   public static String removeIgnoreCase(final String str, final Stringremove) {

5004       if (isEmpty(str) || isEmpty(remove)) {

5005            return str;

5006       }

5007       return replaceIgnoreCase(str, remove, EMPTY, -1);

5008   }

5009

5010   /**

5011    * <p>Removes all occurrences of a character from within the sourcestring.</p>

5012    *

5013    * <p>A {@code null} source string will return {@code null}.

5014    * An empty ("") source string will return the emptystring.</p>

5015    *

5016    * <pre>

5017    * StringUtils.remove(null, *)      = null

5018    * StringUtils.remove("", *)         = ""

5019    * StringUtils.remove("queued", 'u') = "qeed"

5020    * StringUtils.remove("queued", 'z') = "queued"

5021    * </pre>

5022    *

5023    * @param str  the source String tosearch, may be null

5024    * @param remove  the char tosearch for and remove, may be null

5025    * @return the substring with the char removed if found,

5026    *  {@code null} if null Stringinput

5027    * @since 2.1

5028    */

5029   public static String remove(final String str, final char remove) {

5030       if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {

5031            return str;

5032       }

5033       final char[] chars = str.toCharArray();

5034       int pos = 0;

5035       for (int i = 0; i < chars.length; i++) {

5036            if (chars[i] != remove) {

5037                chars[pos++] = chars[i];

5038            }

5039       }

5040       return new String(chars, 0, pos);

5041   }

5042

5043   /**

5044    * <p>Removes each substring of the text String that matches thegiven regular expression.</p>

5045    *

5046    * This method is a {@code null} safe equivalent to:

5047    * <ul>

5048    *  <li>{@codetext.replaceAll(regex, StringUtils.EMPTY)}</li>

5049    *  <li>{@codePattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>

5050    * </ul>

5051    *

5052    * <p>A {@code null} reference passed to this method is ano-op.</p>

5053    *

5054    * <p>Unlike in the {@link #removePattern(String, String)} method,the {@link Pattern#DOTALL} option

5055    * is NOT automatically added.

5056    * To use the DOTALL option prepend<code>"(?s)"</code> to the regex.

5057    * DOTALL is also know as single-line mode in Perl.</p>

5058    *

5059    * <pre>

5060    * StringUtils.removeAll(null, *)     = null

5061    * StringUtils.removeAll("any", null)  = "any"

5062    * StringUtils.removeAll("any", "")    = "any"

5063    * StringUtils.removeAll("any", ".*")  = ""

5064    * StringUtils.removeAll("any", ".+")  = ""

5065    * StringUtils.removeAll("abc", ".?")  = ""

5066    *StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B","&lt;.*&gt;")      ="A\nB"

5067    * StringUtils.removeAll("A&lt;__&gt;\n&lt;__&gt;B","(?s)&lt;.*&gt;")  ="AB"

5068    * StringUtils.removeAll("ABCabc123abc","[a-z]")     ="ABC123"

5069    * </pre>

5070    *

5071    * @param text  text to removefrom, may be null

5072    * @param regex  the regularexpression to which this string is to be matched

5073    * @return  the text with anyremoves processed,

5074    *              {@code null} ifnull String input

5075    *

5076    * @throws java.util.regex.PatternSyntaxException

5077    *              if the regularexpression's syntax is invalid

5078    *

5079    * @see #replaceAll(String, String, String)

5080    * @see #removePattern(String, String)

5081    * @see String#replaceAll(String, String)

5082    * @see java.util.regex.Pattern

5083    * @see java.util.regex.Pattern#DOTALL

5084    * @since 3.5

5085    */

5086   public static String removeAll(final String text, final String regex) {

5087       return replaceAll(text, regex, StringUtils.EMPTY);

5088   }

5089

5090   /**

5091    * <p>Removes the first substring of the text string that matchesthe given regular expression.</p>

5092    *

5093    * This method is a {@code null} safe equivalent to:

5094    * <ul>

5095    *  <li>{@code text.replaceFirst(regex,StringUtils.EMPTY)}</li>

5096    *  <li>{@codePattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>

5097    * </ul>

5098    *

5099    * <p>A {@code null} reference passed to this method is ano-op.</p>

5100    *

5101    * <p>The {@link Pattern#DOTALL} option is NOT automatically added.

5102    * To use the DOTALL option prepend<code>"(?s)"</code> to the regex.

5103    * DOTALL is also know as single-line mode in Perl.</p>

5104    *

5105    * <pre>

5106    * StringUtils.removeFirst(null, *)     = null

5107    * StringUtils.removeFirst("any", null)  = "any"

5108    * StringUtils.removeFirst("any", "")    = "any"

5109    * StringUtils.removeFirst("any", ".*")  = ""

5110    * StringUtils.removeFirst("any", ".+")  = ""

5111    * StringUtils.removeFirst("abc", ".?")  = "bc"

5112    *StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B","&lt;.*&gt;")      ="A\n&lt;__&gt;B"

5113    *StringUtils.removeFirst("A&lt;__&gt;\n&lt;__&gt;B","(?s)&lt;.*&gt;")  ="AB"

5114    * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"

5115    * StringUtils.removeFirst("ABCabc123abc","[a-z]+")      ="ABC123abc"

5116    * </pre>

5117    *

5118    * @param text  text to removefrom, may be null

5119    * @param regex  the regularexpression to which this string is to be matched

5120    * @return  the text with the firstreplacement processed,

5121    *              {@code null} ifnull String input

5122    *

5123    * @throws java.util.regex.PatternSyntaxException

5124    *              if the regularexpression's syntax is invalid

5125    *

5126    * @see #replaceFirst(String, String, String)

5127    * @see String#replaceFirst(String, String)

5128    * @see java.util.regex.Pattern

5129    * @see java.util.regex.Pattern#DOTALL

5130    * @since 3.5

5131    */

5132   public static String removeFirst(final String text, final String regex){

5133       return replaceFirst(text, regex, StringUtils.EMPTY);

5134   }

5135

5136   // Replacing

5137   //-----------------------------------------------------------------------

5138   /**

5139    * <p>Replaces a String with another String inside a larger String,once.</p>

5140    *

5141    * <p>A {@code null} reference passed to this method is ano-op.</p>

5142    *

5143    * <pre>

5144    * StringUtils.replaceOnce(null, *, *)        = null

5145    * StringUtils.replaceOnce("", *, *)          = ""

5146    * StringUtils.replaceOnce("any", null, *)    = "any"

5147    * StringUtils.replaceOnce("any", *, null)    = "any"

5148    * StringUtils.replaceOnce("any", "", *)      = "any"

5149    * StringUtils.replaceOnce("aba", "a", null)  = "aba"

5150    * StringUtils.replaceOnce("aba", "a","")    = "ba"

5151    *StringUtils.replaceOnce("aba", "a", "z")   = "zba"

5152    * </pre>

5153    *

5154    * @see #replace(String text, String searchString, String replacement,int max)

5155    * @param text  text to search andreplace in, may be null

5156    * @param searchString  the Stringto search for, may be null

5157    * @param replacement  the Stringto replace with, may be null

5158    * @return the text with any replacements processed,

5159    *  {@code null} if null Stringinput

5160    */

5161   public static String replaceOnce(final String text, final StringsearchString, final String replacement) {

5162       return replace(text, searchString, replacement, 1);

5163   }

5164

5165   /**

5166    * <p>Case insensitively replaces a String with another Stringinside a larger String, once.</p>

5167    *

5168    * <p>A {@code null} reference passed to this method is ano-op.</p>

5169    *

5170    * <pre>

5171    * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null

5172    * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""

5173    * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"

5174    * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"

5175    * StringUtils.replaceOnceIgnoreCase("any", "",*)      = "any"

5176    * StringUtils.replaceOnceIgnoreCase("aba", "a",null)  = "aba"

5177    * StringUtils.replaceOnceIgnoreCase("aba", "a","")    = "ba"

5178    * StringUtils.replaceOnceIgnoreCase("aba", "a","z")   = "zba"

5179    * StringUtils.replaceOnceIgnoreCase("FoOFoofoo","foo", "") = "Foofoo"

5180    * </pre>

5181    *

5182    * @see #replaceIgnoreCase(String text, String searchString, String replacement,int max)

5183    * @param text  text to search andreplace in, may be null

5184    * @param searchString  the Stringto search for (case insensitive), may be null

5185    * @param replacement  the Stringto replace with, may be null

5186    * @return the text with any replacements processed,

5187    *  {@code null} if null Stringinput

5188    * @since 3.5

5189    */

5190   public static String replaceOnceIgnoreCase(final String text, finalString searchString, final String replacement) {

5191       return replaceIgnoreCase(text, searchString, replacement, 1);

5192   }

5193

5194   /**

5195    * <p>Replaces each substring of the source String that matches thegiven regular expression with the given

5196    * replacement using the {@link Pattern#DOTALL} option. DOTALL is alsoknow as single-line mode in Perl.</p>

5197    *

5198    * This call is a {@code null} safe equivalent to:

5199    * <ul>

5200    * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex,replacement)}</li>

5201    * <li>{@code Pattern.compile(regex,Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>

5202    * </ul>

5203    *

5204    * <p>A {@code null} reference passed to this method is ano-op.</p>

5205    *

5206    * <pre>

5207    * StringUtils.replacePattern(null, *, *)       = null

5208    * StringUtils.replacePattern("any", null, *)   = "any"

5209    * StringUtils.replacePattern("any", *, null)   = "any"

5210    * StringUtils.replacePattern("", "","zzz")    = "zzz"

5211     * StringUtils.replacePattern("",".*", "zzz")  ="zzz"

5212    * StringUtils.replacePattern("", ".+","zzz")  = ""

5213    *StringUtils.replacePattern("&lt;__&gt;\n&lt;__&gt;","&lt;.*&gt;", "z")       = "z"

5214    * StringUtils.replacePattern("ABCabc123", "[a-z]","_")       ="ABC___123"

5215    * StringUtils.replacePattern("ABCabc123","[^A-Z0-9]+", "_")  ="ABC_123"

5216    * StringUtils.replacePattern("ABCabc123","[^A-Z0-9]+", "")   ="ABC123"

5217    * StringUtils.replacePattern("Lorem ipsum  dolor  sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"

5218    * </pre>

5219    *

5220    * @param source

5221    *            the source string

5222    * @param regex

5223    *            the regularexpression to which this string is to be matched

5224    * @param replacement

5225    *            the string to besubstituted for each match

5226    * @return The resulting {@code String}

5227    * @see #replaceAll(String, String, String)

5228    * @see String#replaceAll(String, String)

5229    * @see Pattern#DOTALL

5230    * @since 3.2

5231    * @since 3.5 Changed {@code null} reference passed to this method is ano-op.

5232    */

5233   public static String replacePattern(final String source, final Stringregex, final String replacement) {

5234       if (source == null || regex == null || replacement == null) {

5235            return source;

5236       }

5237       return Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement);

5238   }

5239

5240   /**

5241    * <p>Removes each substring of the source String that matches thegiven regular expression using the DOTALL option.

5242    * </p>

5243    *

5244    * This call is a {@code null} safe equivalent to:

5245    * <ul>

5246    * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex,StringUtils.EMPTY)}</li>

5247    * <li>{@code Pattern.compile(regex,Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>

5248    * </ul>

5249    *

5250    * <p>A {@code null} reference passed to this method is ano-op.</p>

5251    *

5252    * <pre>

5253    * StringUtils.removePattern(null, *)       = null

5254    * StringUtils.removePattern("any", null)   = "any"

5255    * StringUtils.removePattern("A&lt;__&gt;\n&lt;__&gt;B","&lt;.*&gt;")  ="AB"

5256    * StringUtils.removePattern("ABCabc123","[a-z]")    ="ABC123"

5257    * </pre>

5258    *

5259    * @param source

5260    *            the source string

5261    * @param regex

5262    *            the regular expression to which thisstring is to be matched

5263    * @return The resulting {@code String}

5264    * @see #replacePattern(String, String, String)

5265    * @see String#replaceAll(String, String)

5266    * @see Pattern#DOTALL

5267    * @since 3.2

5268    * @since 3.5 Changed {@code null} reference passed to this method is ano-op.

5269    */

5270   public static String removePattern(final String source, final Stringregex) {

5271       return replacePattern(source, regex, StringUtils.EMPTY);

5272   }

5273

5274   /**

5275    * <p>Replaces each substring of the text String that matches thegiven regular expression

5276    * with the given replacement.</p>

5277    *

5278    * This method is a {@code null} safe equivalent to:

5279    * <ul>

5280    *  <li>{@codetext.replaceAll(regex, replacement)}</li>

5281    *  <li>{@codePattern.compile(regex).matcher(text).replaceAll(replacement)}</li>

5282    * </ul>

5283    *

5284    * <p>A {@code null} reference passed to this method is ano-op.</p>

5285    *

5286    * <p>Unlike in the {@link #replacePattern(String, String, String)}method, the {@link Pattern#DOTALL} option

5287    * is NOT automatically added.

5288    * To use the DOTALL option prepend<code>"(?s)"</code> to the regex.

5289    * DOTALL is also know as single-line mode in Perl.</p>

5290    *

5291    * <pre>

5292    * StringUtils.replaceAll(null, *, *)       = null

5293    * StringUtils.replaceAll("any", null, *)   = "any"

5294    * StringUtils.replaceAll("any", *, null)   = "any"

5295    * StringUtils.replaceAll("", "","zzz")    = "zzz"

5296    * StringUtils.replaceAll("", ".*","zzz")  = "zzz"

5297    * StringUtils.replaceAll("", ".+","zzz")  = ""

5298    * StringUtils.replaceAll("abc", "","ZZ")  ="ZZaZZbZZcZZ"

5299    *StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;","&lt;.*&gt;", "z")      = "z\nz"

5300    * StringUtils.replaceAll("&lt;__&gt;\n&lt;__&gt;","(?s)&lt;.*&gt;", "z")  = "z"

5301    * StringUtils.replaceAll("ABCabc123", "[a-z]","_")       ="ABC___123"

5302    * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+","_")  = "ABC_123"

5303    * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+","")   = "ABC123"

5304    * StringUtils.replaceAll("Lorem ipsum  dolor  sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"

5305    * </pre>

5306    *

5307    * @param text  text to search andreplace in, may be null

5308    * @param regex  the regularexpression to which this string is to be matched

5309    * @param replacement  the stringto be substituted for each match

5310    * @return  the text with anyreplacements processed,

5311    *              {@code null} ifnull String input

5312    *

5313    * @throws java.util.regex.PatternSyntaxException

5314    *              if the regularexpression's syntax is invalid

5315    *

5316    * @see #replacePattern(String, String, String)

5317    * @see String#replaceAll(String, String)

5318    * @see java.util.regex.Pattern

5319    * @see java.util.regex.Pattern#DOTALL

5320    * @since 3.5

5321    */

5322   public static String replaceAll(final String text, final String regex,final String replacement) {

5323       if (text == null || regex == null|| replacement == null ) {

5324            return text;

5325       }

5326       return text.replaceAll(regex, replacement);

5327   }

5328

5329   /**

5330    * <p>Replaces the first substring of the text string that matchesthe given regular expression

5331    * with the given replacement.</p>

5332    *

5333    * This method is a {@code null} safe equivalent to:

5334    * <ul>

5335    *  <li>{@code text.replaceFirst(regex,replacement)}</li>

5336    *  <li>{@codePattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>

5337    * </ul>

5338    *

5339    * <p>A {@code null} reference passed to this method is ano-op.</p>

5340    *

5341    * <p>The {@link Pattern#DOTALL} option is NOT automatically added.

5342    * To use the DOTALL option prepend<code>"(?s)"</code> to the regex.

5343    * DOTALL is also know as single-line mode in Perl.</p>

5344    *

5345    * <pre>

5346    * StringUtils.replaceFirst(null, *, *)       = null

5347    * StringUtils.replaceFirst("any", null, *)   = "any"

5348    * StringUtils.replaceFirst("any", *, null)   = "any"

5349    * StringUtils.replaceFirst("", "","zzz")    = "zzz"

5350    * StringUtils.replaceFirst("", ".*","zzz")  = "zzz"

5351    * StringUtils.replaceFirst("", ".+","zzz")  = ""

5352    * StringUtils.replaceFirst("abc", "","ZZ")  = "ZZabc"

5353    *StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;","&lt;.*&gt;", "z")      ="z\n&lt;__&gt;"

5354    *StringUtils.replaceFirst("&lt;__&gt;\n&lt;__&gt;","(?s)&lt;.*&gt;", "z")  = "z"

5355    * StringUtils.replaceFirst("ABCabc123", "[a-z]","_")          ="ABC_bc123"

5356    * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+","_")  = "ABC_123abc"

5357    * StringUtils.replaceFirst("ABCabc123abc","[^A-Z0-9]+", "")   ="ABC123abc"

5358    * StringUtils.replaceFirst("Lorem ipsum  dolor  sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor  sit"

5359    * </pre>

5360     *

5361    * @param text  text to search andreplace in, may be null

5362    * @param regex  the regularexpression to which this string is to be matched

5363    * @param replacement  the stringto be substituted for the first match

5364    * @return  the text with the firstreplacement processed,

5365    *              {@code null} ifnull String input

5366    *

5367    * @throws java.util.regex.PatternSyntaxException

5368    *              if the regularexpression's syntax is invalid

5369    *

5370    * @see String#replaceFirst(String, String)

5371    * @see java.util.regex.Pattern

5372    * @see java.util.regex.Pattern#DOTALL

5373    * @since 3.5

5374    */

5375   public static String replaceFirst(final String text, final String regex,final String replacement) {

5376       if (text == null || regex == null|| replacement == null ) {

5377            return text;

5378       }

5379       return text.replaceFirst(regex, replacement);

5380   }

5381

5382   /**

5383    * <p>Replaces all occurrences of a String within anotherString.</p>

5384    *

5385    * <p>A {@code null} reference passed to this method is ano-op.</p>

5386    *

5387    * <pre>

5388    * StringUtils.replace(null, *, *)       = null

5389    * StringUtils.replace("", *, *)          = ""

5390    * StringUtils.replace("any", null, *)    = "any"

5391    * StringUtils.replace("any", *, null)    = "any"

5392    * StringUtils.replace("any", "", *)      = "any"

5393    * StringUtils.replace("aba", "a", null)  = "aba"

5394    * StringUtils.replace("aba", "a", "")    = "b"

5395    * StringUtils.replace("aba", "a","z")   = "zbz"

5396    * </pre>

5397    *

5398    * @see #replace(String text, String searchString, String replacement,int max)

5399    * @param text  text to search andreplace in, may be null

5400    * @param searchString  the Stringto search for, may be null

5401    * @param replacement  the Stringto replace it with, may be null

5402    * @return the text with any replacements processed,

5403    *  {@code null} if null Stringinput

5404    */

5405   public static String replace(final String text, final StringsearchString, final String replacement) {

5406       return replace(text, searchString, replacement, -1);

5407   }

5408

5409   /**

5410   * <p>Case insensitively replaces all occurrences of a Stringwithin another String.</p>

5411   *

5412   * <p>A {@code null} reference passed to this method is ano-op.</p>

5413   *

5414   * <pre>

5415   * StringUtils.replaceIgnoreCase(null, *, *)        = null

5416   * StringUtils.replaceIgnoreCase("", *, *)          = ""

5417   * StringUtils.replaceIgnoreCase("any", null, *)    = "any"

5418   * StringUtils.replaceIgnoreCase("any", *, null)    = "any"

5419   * StringUtils.replaceIgnoreCase("any", "", *)      = "any"

5420   * StringUtils.replaceIgnoreCase("aba", "a",null)  = "aba"

5421   * StringUtils.replaceIgnoreCase("abA", "A","")    = "b"

5422   * StringUtils.replaceIgnoreCase("aba", "A","z")   = "zbz"

5423   * </pre>

5424   *

5425   * @see #replaceIgnoreCase(String text, String searchString, Stringreplacement, int max)

5426   * @param text  text to search andreplace in, may be null

5427   * @param searchString  the Stringto search for (case insensitive), may be null

5428   * @param replacement  the Stringto replace it with, may be null

5429   * @return the text with any replacements processed,

5430   *  {@code null} if null Stringinput

5431   * @since 3.5

5432   */

5433  public static String replaceIgnoreCase(final String text, final StringsearchString, final String replacement) {

5434      return replaceIgnoreCase(text, searchString, replacement, -1);

5435  }

5436

5437   /**

5438    * <p>Replaces a String with another String inside a larger String,

5439    * for the first {@code max} values of the search String.</p>

5440    *

5441    * <p>A {@code null} reference passed to this method is ano-op.</p>

5442    *

5443    * <pre>

5444    * StringUtils.replace(null, *, *, *)         = null

5445    * StringUtils.replace("", *, *, *)           = ""

5446    * StringUtils.replace("any", null, *, *)     = "any"

5447    * StringUtils.replace("any", *, null, *)     = "any"

5448    * StringUtils.replace("any", "", *, *)       = "any"

5449    * StringUtils.replace("any", *, *, 0)        = "any"

5450    * StringUtils.replace("abaa", "a", null, -1) ="abaa"

5451    * StringUtils.replace("abaa", "a", "",-1)   = "b"

5452    * StringUtils.replace("abaa", "a", "z",0)   = "abaa"

5453    * StringUtils.replace("abaa", "a", "z",1)   = "zbaa"

5454    * StringUtils.replace("abaa", "a", "z",2)   = "zbza"

5455    * StringUtils.replace("abaa", "a", "z",-1)  = "zbzz"

5456    * </pre>

5457    *

5458    * @param text  text to search andreplace in, may be null

5459    * @param searchString  the Stringto search for, may be null

5460    * @param replacement  the Stringto replace it with, may be null

5461    * @param max  maximum number ofvalues to replace, or {@code -1} if no maximum

5462    * @return the text with any replacements processed,

5463    *  {@code null} if null Stringinput

5464    */

5465   public static String replace(final String text, final StringsearchString, final String replacement, final int max) {

5466       return replace(text, searchString, replacement, max, false);

5467   }

5468

5469   /**

5470    * <p>Replaces a String with another String inside a larger String,

5471    * for the first {@code max} values of the search String,

5472    * case sensitively/insensisitively based on {@code ignoreCase}value.</p>

5473    *

5474    * <p>A {@code null} reference passed to this method is ano-op.</p>

5475    *

5476    * <pre>

5477    * StringUtils.replace(null, *, *, *, false)         = null

5478    * StringUtils.replace("", *, *, *, false)           = ""

5479    * StringUtils.replace("any", null, *, *, false)     = "any"

5480    * StringUtils.replace("any", *, null, *, false)     = "any"

5481    * StringUtils.replace("any", "", *, *, false)       = "any"

5482    * StringUtils.replace("any", *, *, 0, false)        = "any"

5483    * StringUtils.replace("abaa", "a", null, -1, false)= "abaa"

5484    * StringUtils.replace("abaa", "a", "", -1,false)   = "b"

5485    * StringUtils.replace("abaa", "a", "z", 0,false)   = "abaa"

5486    * StringUtils.replace("abaa", "A", "z", 1,false)   = "abaa"

5487    * StringUtils.replace("abaa", "A", "z", 1,true)   = "zbaa"

5488    * StringUtils.replace("abAa", "a", "z", 2,true)   = "zbza"

5489    * StringUtils.replace("abAa", "a", "z",-1, true)  = "zbzz"

5490    * </pre>

5491    *

5492    * @param text  text to search andreplace in, may be null

5493    * @param searchString  the Stringto search for (case insensitive), may be null

5494    * @param replacement  the Stringto replace it with, may be null

5495    * @param max  maximum number ofvalues to replace, or {@code -1} if no maximum

5496    * @param ignoreCase if true replace is case insensitive, otherwise casesensitive

5497    * @return the text with any replacements processed,

5498    *  {@code null} if null Stringinput

5499    */

5500    private static String replace(final String text, String searchString,final String replacement, int max, final boolean ignoreCase) {

5501        if (isEmpty(text) || isEmpty(searchString) || replacement == null || max== 0) {

5502            return text;

5503        }

5504        String searchText = text;

5505        if (ignoreCase) {

5506             searchText = text.toLowerCase();

5507             searchString =searchString.toLowerCase();

5508        }

5509        int start = 0;

5510        int end = searchText.indexOf(searchString, start);

5511        if (end == INDEX_NOT_FOUND) {

5512             return text;

5513        }

5514        final int replLength = searchString.length();

5515        int increase = replacement.length() - replLength;

5516        increase = increase < 0 ? 0 : increase;

5517        increase *= max < 0 ? 16 : max > 64 ? 64 : max;

5518        final StringBuilder buf = new StringBuilder(text.length() + increase);

5519        while (end != INDEX_NOT_FOUND) {

5520             buf.append(text.substring(start,end)).append(replacement);

5521             start = end + replLength;

5522             if (--max == 0) {

5523                 break;

5524             }

5525            end =searchText.indexOf(searchString, start);

5526        }

5527        buf.append(text.substring(start));

5528        return buf.toString();

5529    }

5530

5531   /**

5532    * <p>Case insensitively replaces a String with another String insidea larger String,

5533    * for the first {@code max} values of the search String.</p>

5534    *

5535    * <p>A {@code null} reference passed to this method is ano-op.</p>

5536    *

5537    * <pre>

5538    * StringUtils.replaceIgnoreCase(null, *, *, *)         = null

5539    * StringUtils.replaceIgnoreCase("", *, *, *)           = ""

5540    * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"

5541    * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"

5542    * StringUtils.replaceIgnoreCase("any", "", *,*)       = "any"

5543    * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"

5544    * StringUtils.replaceIgnoreCase("abaa", "a", null,-1) = "abaa"

5545    * StringUtils.replaceIgnoreCase("abaa", "a","", -1)   = "b"

5546    * StringUtils.replaceIgnoreCase("abaa", "a","z", 0)   = "abaa"

5547    * StringUtils.replaceIgnoreCase("abaa", "A","z", 1)   = "zbaa"

5548    * StringUtils.replaceIgnoreCase("abAa", "a", "z",2)   = "zbza"

5549    * StringUtils.replaceIgnoreCase("abAa", "a","z", -1)  = "zbzz"

5550    * </pre>

5551    *

5552    * @param text  text to search andreplace in, may be null

5553    * @param searchString  the Stringto search for (case insensitive), may be null

5554    * @param replacement  the Stringto replace it with, may be null

5555    * @param max  maximum number ofvalues to replace, or {@code -1} if no maximum

5556    * @return the text with any replacements processed,

5557    *  {@code null} if null Stringinput

5558    * @since 3.5

5559    */

5560   public static String replaceIgnoreCase(final String text, final StringsearchString, final String replacement, final int max) {

5561       return replace(text, searchString, replacement, max, true);

5562   }

5563

5564   /**

5565    * <p>

5566    * Replaces all occurrences of Strings within another String.

5567    * </p>

5568    *

5569    * <p>

5570    * A {@code null} reference passed to this method is a no-op, or if

5571    * any "search string" or "string to replace" isnull, that replace will be

5572    * ignored. This will not repeat. For repeating replaces, call the

5573    * overloaded method.

5574    * </p>

5575    *

5576    * <pre>

5577    *  StringUtils.replaceEach(null,*, *)        = null

5578    * StringUtils.replaceEach("", *, *)          = ""

5579    * StringUtils.replaceEach("aba", null, null) = "aba"

5580    * StringUtils.replaceEach("aba", new String[0], null) ="aba"

5581    * StringUtils.replaceEach("aba", null, new String[0]) ="aba"

5582    * StringUtils.replaceEach("aba", new String[]{"a"},null)  = "aba"

5583    * StringUtils.replaceEach("aba", new String[]{"a"},new String[]{""})  ="b"

5584    * StringUtils.replaceEach("aba", new String[]{null}, newString[]{"a"})  ="aba"

5585    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"w", "t"})  = "wcte"

5586    *  (example of how it does notrepeat)

5587    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"d", "t"})  = "dcte"

5588    * </pre>

5589    *

5590    * @param text

5591    *            text to search andreplace in, no-op if null

5592    * @param searchList

5593    *            the Strings to search for, no-op ifnull

5594    * @param replacementList

5595    *            the Strings toreplace them with, no-op if null

5596    * @return the text with any replacements processed, {@code null} if

5597    *         null String input

5598    * @throws IllegalArgumentException

5599    *             if the lengths ofthe arrays are not the same (null is ok,

5600    *             and/or size 0)

5601    * @since 2.4

5602    */

5603   public static String replaceEach(final String text, final String[]searchList, final String[] replacementList) {

5604       return replaceEach(text, searchList, replacementList, false, 0);

5605   }

5606

5607   /**

5608    * <p>

5609    * Replaces all occurrences of Strings within another String.

5610    * </p>

5611    *

5612    * <p>

5613    * A {@code null} reference passed to this method is a no-op, or if

5614    * any "search string" or "string to replace" isnull, that replace will be

5615    * ignored.

5616    * </p>

5617    *

5618    * <pre>

5619    * StringUtils.replaceEachRepeatedly(null, *, *) = null

5620    * StringUtils.replaceEachRepeatedly("", *, *) = ""

5621    * StringUtils.replaceEachRepeatedly("aba", null, null) ="aba"

5622    * StringUtils.replaceEachRepeatedly("aba", new String[0], null)= "aba"

5623    * StringUtils.replaceEachRepeatedly("aba", null, new String[0])= "aba"

5624    *  StringUtils.replaceEachRepeatedly("aba",new String[]{"a"}, null) = "aba"

5625    * StringUtils.replaceEachRepeatedly("aba", newString[]{"a"}, new String[]{""}) = "b"

5626    * StringUtils.replaceEachRepeatedly("aba", new String[]{null},new String[]{"a"}) = "aba"

5627    * StringUtils.replaceEachRepeatedly("abcde", newString[]{"ab", "d"}, new String[]{"w","t"}) = "wcte"

5628    *  (example of how it repeats)

5629    * StringUtils.replaceEachRepeatedly("abcde", newString[]{"ab", "d"}, new String[]{"d", "t"})= "tcte"

5630    * StringUtils.replaceEachRepeatedly("abcde", newString[]{"ab", "d"}, new String[]{"d","ab"}) = IllegalStateException

5631    * </pre>

5632    *

5633    * @param text

5634    *            text to search andreplace in, no-op if null

5635    * @param searchList

5636    *            the Strings to searchfor, no-op if null

5637    * @param replacementList

5638    *            the Strings toreplace them with, no-op if null

5639    * @return the text with any replacements processed, {@code null} if

5640    *         null String input

5641    * @throws IllegalStateException

5642    *             if the search isrepeating and there is an endless loop due

5643    *             to outputs of one being inputs toanother

5644    * @throws IllegalArgumentException

5645    *             if the lengths ofthe arrays are not the same (null is ok,

5646    *             and/or size 0)

5647    * @since 2.4

5648    */

5649   public static String replaceEachRepeatedly(final String text, finalString[] searchList, final String[] replacementList) {

5650       // timeToLive should be 0 if not used or nothing to replace, else it's

5651       // the length of the replace array

5652       final int timeToLive = searchList == null ? 0 : searchList.length;

5653       return replaceEach(text, searchList, replacementList, true, timeToLive);

5654   }

5655

5656   /**

5657    * <p>

5658    * Replace all occurrences of Strings within another String.

5659    * This is a private recursive helper method for {@link#replaceEachRepeatedly(String, String[], String[])} and

5660    * {@link #replaceEach(String, String[], String[])}

5661    * </p>

5662    *

5663    * <p>

5664    * A {@code null} reference passed to this method is a no-op, or if

5665    * any "search string" or "string to replace" isnull, that replace will be

5666    * ignored.

5667    * </p>

5668    *

5669    * <pre>

5670    *  StringUtils.replaceEach(null,*, *, *, *) = null

5671    * StringUtils.replaceEach("", *, *, *, *) = ""

5672    * StringUtils.replaceEach("aba", null, null, *, *) ="aba"

5673    * StringUtils.replaceEach("aba", new String[0], null, *, *) ="aba"

5674    * StringUtils.replaceEach("aba", null, new String[0], *, *) ="aba"

5675    * StringUtils.replaceEach("aba", new String[]{"a"},null, *, *) = "aba"

5676    * StringUtils.replaceEach("aba", new String[]{"a"},new String[]{""}, *, >=0) = "b"

5677    * StringUtils.replaceEach("aba", new String[]{null}, newString[]{"a"}, *, >=0) = "aba"

5678    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"w", "t"}, *, >=0) ="wcte"

5679    *  (example of how it repeats)

5680    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"d", "t"}, false, >=0) ="dcte"

5681    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"d", "t"}, true, >=2) ="tcte"

5682    * StringUtils.replaceEach("abcde", new String[]{"ab","d"}, new String[]{"d", "ab"}, *, *) =IllegalStateException

5683    * </pre>

5684    *

5685    * @param text

5686    *            text to search andreplace in, no-op if null

5687    * @param searchList

5688    *            the Strings to searchfor, no-op if null

5689    * @param replacementList

5690    *            the Strings toreplace them with, no-op if null

5691    * @param repeat if true, then replace repeatedly

5692    *       until there are no morepossible replacements or timeToLive < 0

5693    * @param timeToLive

5694    *            if less than 0 thenthere is a circular reference and endless

5695    *            loop

5696    * @return the text with any replacements processed, {@code null} if

5697    *         null String input

5698    * @throws IllegalStateException

5699    *             if the search isrepeating and there is an endless loop due

5700    *             to outputs of onebeing inputs to another

5701    * @throws IllegalArgumentException

5702    *             if the lengths ofthe arrays are not the same (null is ok,

5703    *             and/or size 0)

5704    * @since 2.4

5705    */

5706   private static String replaceEach(

5707            final String text, final String[]searchList, final String[] replacementList, final boolean repeat, final inttimeToLive) {

5708

5709       // mchyzer Performance note: This creates very few new objects (onemajor goal)

5710       // let me know if there are performance requests, we can create aharness to measure

5711

5712       if (text == null || text.isEmpty() || searchList == null ||

5713                searchList.length == 0 ||replacementList == null || replacementList.length == 0) {

5714            return text;

5715       }

5716

5717       // if recursing, this shouldn't be less than 0

5718       if (timeToLive < 0) {

5719            throw newIllegalStateException("Aborting to protect against StackOverflowError -" +

5720                                           "outputof one loop is the input of another");

5721       }

5722

5723       final int searchLength = searchList.length;

5724       final int replacementLength = replacementList.length;

5725

5726       // make sure lengths are ok, these need to be equal

5727       if (searchLength != replacementLength) {

5728            throw newIllegalArgumentException("Search and Replace array lengths don't match:"

5729                + searchLength

5730                + " vs "

5731                + replacementLength);

5732       }

5733

5734       // keep track of which still have matches

5735       final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];

5736

5737       // index on index that the match was found

5738       int textIndex = -1;

5739       int replaceIndex = -1;

5740       int tempIndex = -1;

5741

5742       // index of replace array that will replace the search string found

5743       // NOTE: logic duplicated below START

5744       for (int i = 0; i < searchLength; i++) {

5745            if (noMoreMatchesForReplIndex[i] ||searchList[i] == null ||

5746                    searchList[i].isEmpty() ||replacementList[i] == null) {

5747                continue;

5748            }

5749            tempIndex =text.indexOf(searchList[i]);

5750

5751            // see if we need to keep searchingfor this

5752            if (tempIndex == -1) {

5753                noMoreMatchesForReplIndex[i] =true;

5754            } else {

5755                if (textIndex == -1 ||tempIndex < textIndex) {

5756                    textIndex = tempIndex;

5757                    replaceIndex = i;

5758                }

5759            }

5760       }

5761       // NOTE: logic mostly below END

5762

5763       // no search strings found, we are done

5764       if (textIndex == -1) {

5765            return text;

5766       }

5767

5768       int start = 0;

5769

5770       // get a good guess on the size of the result buffer so it doesn't haveto double if it goes over a bit

5771       int increase = 0;

5772

5773       // count the replacement text elements that are larger than theircorresponding text being replaced

5774       for (int i = 0; i < searchList.length; i++) {

5775            if (searchList[i] == null ||replacementList[i] == null) {

5776                continue;

5777            }

5778            final int greater =replacementList[i].length() - searchList[i].length();

5779            if (greater > 0) {

5780                increase += 3 * greater; //assume 3 matches

5781            }

5782       }

5783       // have upper-bound at 20% increase, then let Java take over

5784       increase = Math.min(increase, text.length() / 5);

5785

5786       final StringBuilder buf = new StringBuilder(text.length() + increase);

5787

5788       while (textIndex != -1) {

5789

5790            for (int i = start; i <textIndex; i++) {

5791                buf.append(text.charAt(i));

5792            }

5793            buf.append(replacementList[replaceIndex]);

5794

5795            start = textIndex +searchList[replaceIndex].length();

5796

5797            textIndex = -1;

5798            replaceIndex = -1;

5799            tempIndex = -1;

5800            // find the next earliest match

5801            // NOTE: logic mostly duplicatedabove START

5802            for (int i = 0; i <searchLength; i++) {

5803                if(noMoreMatchesForReplIndex[i] || searchList[i] == null ||

5804                        searchList[i].isEmpty()|| replacementList[i] == null) {

5805                    continue;

5806                }

5807                tempIndex =text.indexOf(searchList[i], start);

5808

5809                // see if we need to keep searchingfor this

5810                if (tempIndex == -1) {

5811                   noMoreMatchesForReplIndex[i] = true;

5812                } else {

5813                    if (textIndex == -1 ||tempIndex < textIndex) {

5814                        textIndex = tempIndex;

5815                        replaceIndex = i;

5816                    }

5817                }

5818            }

5819            // NOTE: logic duplicated above END

5820

5821       }

5822       final int textLength = text.length();

5823       for (int i = start; i < textLength; i++) {

5824            buf.append(text.charAt(i));

5825       }

5826       final String result = buf.toString();

5827       if (!repeat) {

5828            return result;

5829       }

5830

5831       return replaceEach(result, searchList, replacementList, repeat,timeToLive - 1);

5832   }

5833

5834   // Replace, character based

5835   //-----------------------------------------------------------------------

5836   /**

5837    * <p>Replaces all occurrences of a character in a String withanother.

5838    * This is a null-safe version of {@link String#replace(char,char)}.</p>

5839    *

5840    * <p>A {@code null} string input returns {@code null}.

5841    * An empty ("") string input returns an emptystring.</p>

5842    *

5843    * <pre>

5844    * StringUtils.replaceChars(null, *, *)        = null

5845    * StringUtils.replaceChars("", *, *)          = ""

5846    * StringUtils.replaceChars("abcba", 'b', 'y') ="aycya"

5847    * StringUtils.replaceChars("abcba", 'z', 'y') ="abcba"

5848    * </pre>

5849    *

5850    * @param str  String to replacecharacters in, may be null

5851    * @param searchChar  the characterto search for, may be null

5852    * @param replaceChar  thecharacter to replace, may be null

5853    * @return modified String, {@code null} if null string input

5854    * @since 2.0

5855    */

5856   public static String replaceChars(final String str, final charsearchChar, final char replaceChar) {

5857       if (str == null) {

5858            return null;

5859       }

5860       return str.replace(searchChar, replaceChar);

5861   }

5862

5863   /**

5864    * <p>Replaces multiple characters in a String in one go.

5865    * This method can also be used to delete characters.</p>

5866    *

5867    * <p>For example:<br>

5868    * <code>replaceChars(&quot;hello&quot;,&quot;ho&quot;, &quot;jy&quot;) = jelly</code>.</p>

5869    *

5870    * <p>A {@code null} string input returns {@code null}.

5871    * An empty ("") string input returns an empty string.

5872    * A null or empty set of search characters returns the inputstring.</p>

5873    *

5874    * <p>The length of the search characters should normally equal thelength

5875    * of the replace characters.

5876    * If the search characters is longer, then the extra search characters

5877    * are deleted.

5878    * If the search characters is shorter, then the extra replace characters

5879    * are ignored.</p>

5880    *

5881    * <pre>

5882    * StringUtils.replaceChars(null, *, *)           = null

5883    * StringUtils.replaceChars("", *, *)             = ""

5884    * StringUtils.replaceChars("abc", null, *)       = "abc"

5885    * StringUtils.replaceChars("abc", "", *)         = "abc"

5886    * StringUtils.replaceChars("abc", "b", null)     = "ac"

5887    * StringUtils.replaceChars("abc", "b","")       = "ac"

5888    * StringUtils.replaceChars("abcba", "bc","yz")  = "ayzya"

5889    * StringUtils.replaceChars("abcba", "bc","y")   = "ayya"

5890    * StringUtils.replaceChars("abcba", "bc","yzx") = "ayzya"

5891    * </pre>

5892    *

5893    * @param str  String to replacecharacters in, may be null

5894    * @param searchChars  a set ofcharacters to search for, may be null

5895    * @param replaceChars  a set ofcharacters to replace, may be null

5896    * @return modified String, {@code null} if null string input

5897    * @since 2.0

5898    */

5899   public static String replaceChars(final String str, final StringsearchChars, String replaceChars) {

5900       if (isEmpty(str) || isEmpty(searchChars)) {

5901            return str;

5902       }

5903       if (replaceChars == null) {

5904            replaceChars = EMPTY;

5905       }

5906       boolean modified = false;

5907       final int replaceCharsLength = replaceChars.length();

5908       final int strLength = str.length();

5909       final StringBuilder buf = new StringBuilder(strLength);

5910       for (int i = 0; i < strLength; i++) {

5911            final char ch = str.charAt(i);

5912            final int index =searchChars.indexOf(ch);

5913            if (index >= 0) {

5914               modified = true;

5915                if (index <replaceCharsLength) {

5916                   buf.append(replaceChars.charAt(index));

5917                }

5918            } else {

5919                buf.append(ch);

5920            }

5921       }

5922       if (modified) {

5923            return buf.toString();

5924       }

5925       return str;

5926   }

5927

5928   // Overlay

5929   //-----------------------------------------------------------------------

5930   /**

5931    * <p>Overlays part of a String with another String.</p>

5932    *

5933    * <p>A {@code null} string input returns {@code null}.

5934    * A negative index is treated as zero.

5935    * An index greater than the string length is treated as the stringlength.

5936    * The start index is always thesmaller of the two indices.</p>

5937    *

5938    * <pre>

5939    * StringUtils.overlay(null, *, *, *)            = null

5940    * StringUtils.overlay("", "abc", 0, 0)          = "abc"

5941    * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"

5942    * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"

5943    * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"

5944    * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"

5945    * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"

5946    * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"

5947    * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"

5948    * StringUtils.overlay("abcdef", "zzzz", -2, -3) ="zzzzabcdef"

5949    * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"

5950    * </pre>

5951    *

5952    * @param str  the String to dooverlaying in, may be null

5953    * @param overlay  the String tooverlay, may be null

5954    * @param start  the position to start overlaying at

5955    * @param end  the position to stopoverlaying before

5956    * @return overlayed String, {@code null} if null String input

5957    * @since 2.0

5958    */

5959   public static String overlay(final String str, String overlay, intstart, int end) {

5960       if (str == null) {

5961            return null;

5962       }

5963       if (overlay == null) {

5964            overlay = EMPTY;

5965       }

5966       final int len = str.length();

5967       if (start < 0) {

5968            start = 0;

5969       }

5970       if (start > len) {

5971            start = len;

5972       }

5973       if (end < 0) {

5974            end = 0;

5975       }

5976       if (end > len) {

5977            end = len;

5978       }

5979       if (start > end) {

5980            final int temp = start;

5981            start = end;

5982            end = temp;

5983       }

5984       return new StringBuilder(len + start - end + overlay.length() + 1)

5985            .append(str.substring(0, start))

5986            .append(overlay)

5987            .append(str.substring(end))

5988            .toString();

5989   }

5990

5991   // Chomping

5992   //-----------------------------------------------------------------------

5993   /**

5994    * <p>Removes one newline from end of a String if it's there,

5995    * otherwise leave it alone.  Anewline is &quot;{@code \n}&quot;,

5996    * &quot;{@code \r}&quot;, or &quot;{@code\r\n}&quot;.</p>

5997    *

5998    * <p>NOTE: This method changed in 2.0.

5999    * It now more closely matches Perl chomp.</p>

6000    *

6001    * <pre>

6002    * StringUtils.chomp(null)         = null

6003    * StringUtils.chomp("")            = ""

6004    * StringUtils.chomp("abc \r")      = "abc "

6005    * StringUtils.chomp("abc\n")       = "abc"

6006    * StringUtils.chomp("abc\r\n")     = "abc"

6007    * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"

6008    * StringUtils.chomp("abc\n\r")     = "abc\n"

6009    * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"

6010    * StringUtils.chomp("\r")          = ""

6011    * StringUtils.chomp("\n")          = ""

6012    * StringUtils.chomp("\r\n")       = ""

6013    * </pre>

6014    *

6015    * @param str  the String to chompa newline from, may be null

6016    * @return String without newline, {@code null} if null String input

6017    */

6018   public static String chomp(final String str) {

6019       if (isEmpty(str)) {

6020            return str;

6021       }

6022

6023       if (str.length() == 1) {

6024            final char ch = str.charAt(0);

6025            if (ch == CharUtils.CR || ch ==CharUtils.LF) {

6026                return EMPTY;

6027            }

6028            return str;

6029       }

6030

6031       int lastIdx = str.length() - 1;

6032       final char last = str.charAt(lastIdx);

6033

6034       if (last == CharUtils.LF) {

6035            if (str.charAt(lastIdx - 1) ==CharUtils.CR) {

6036                lastIdx--;

6037            }

6038       } else if (last != CharUtils.CR) {

6039            lastIdx++;

6040       }

6041       return str.substring(0, lastIdx);

6042   }

6043

6044   /**

6045    * <p>Removes {@code separator} from the end of

6046    * {@code str} if it's there, otherwise leave it alone.</p>

6047    *

6048    * <p>NOTE: This method changed in version 2.0.

6049    * It now more closely matches Perl chomp.

6050    * For the previous behavior, use {@link #substringBeforeLast(String,String)}.

6051    * This method uses {@link String#endsWith(String)}.</p>

6052    *

6053    * <pre>

6054    * StringUtils.chomp(null, *)        = null

6055    * StringUtils.chomp("", *)          = ""

6056    * StringUtils.chomp("foobar", "bar") ="foo"

6057    * StringUtils.chomp("foobar", "baz") ="foobar"

6058    * StringUtils.chomp("foo", "foo")    = ""

6059    * StringUtils.chomp("foo ", "foo")   = "foo "

6060    * StringUtils.chomp(" foo", "foo")   = " "

6061    * StringUtils.chomp("foo", "foooo")  = "foo"

6062    * StringUtils.chomp("foo", "")       = "foo"

6063    * StringUtils.chomp("foo", null)     = "foo"

6064    * </pre>

6065    *

6066    * @param str  the String to chompfrom, may be null

6067    * @param separator  separatorString, may be null

6068    * @return String without trailing separator, {@code null} if null Stringinput

6069    * @deprecated This feature will be removed in Lang 4.0, use {@linkStringUtils#removeEnd(String, String)} instead

6070    */

6071   @Deprecated

6072   public static String chomp(final String str, final String separator) {

6073       return removeEnd(str,separator);

6074   }

6075

6076   // Chopping

6077   //-----------------------------------------------------------------------

6078   /**

6079    * <p>Remove the last character from a String.</p>

6080    *

6081    * <p>If the String ends in {@code \r\n}, then remove both

6082    * of them.</p>

6083    *

6084    * <pre>

6085    * StringUtils.chop(null)         = null

6086    * StringUtils.chop("")            = ""

6087    * StringUtils.chop("abc \r")      = "abc "

6088    * StringUtils.chop("abc\n")       = "abc"

6089    * StringUtils.chop("abc\r\n")     = "abc"

6090    * StringUtils.chop("abc")         = "ab"

6091    * StringUtils.chop("abc\nabc")    = "abc\nab"

6092    * StringUtils.chop("a")           = ""

6093    * StringUtils.chop("\r")          = ""

6094    *StringUtils.chop("\n")         = ""

6095    * StringUtils.chop("\r\n")        = ""

6096    * </pre>

6097    *

6098    * @param str  the String to choplast character from, may be null

6099    * @return String without last character, {@code null} if null Stringinput

6100    */

6101   public static String chop(final String str) {

6102       if (str == null) {

6103            return null;

6104       }

6105       final int strLen = str.length();

6106       if (strLen < 2) {

6107            return EMPTY;

6108       }

6109       final int lastIdx = strLen - 1;

6110       final String ret = str.substring(0, lastIdx);

6111       final char last = str.charAt(lastIdx);

6112       if (last == CharUtils.LF && ret.charAt(lastIdx - 1) ==CharUtils.CR) {

6113            return ret.substring(0, lastIdx -1);

6114       }

6115       return ret;

6116   }

6117

6118   // Conversion

6119   //-----------------------------------------------------------------------

6120

6121   // Padding

6122   //-----------------------------------------------------------------------

6123   /**

6124    * <p>Repeat a String {@code repeat} times to form a

6125    * new String.</p>

6126    *

6127    * <pre>

6128    * StringUtils.repeat(null, 2) = null

6129    * StringUtils.repeat("", 0)  = ""

6130    * StringUtils.repeat("", 2)  = ""

6131    * StringUtils.repeat("a", 3) = "aaa"

6132    * StringUtils.repeat("ab", 2) = "abab"

6133    * StringUtils.repeat("a", -2) = ""

6134    * </pre>

6135    *

6136    * @param str  the String torepeat, may be null

6137    * @param repeat  number of timesto repeat str, negative treated as zero

6138    * @return a new String consisting of the original String repeated,

6139    *  {@code null} if null Stringinput

6140    */

6141   public static String repeat(final String str, final int repeat) {

6142       // Performance tuned for 2.0 (JDK1.4)

6143

6144       if (str == null) {

6145            return null;

6146       }

6147       if (repeat <= 0) {

6148            return EMPTY;

6149       }

6150       final int inputLength = str.length();

6151       if (repeat == 1 || inputLength == 0) {

6152            return str;

6153       }

6154       if (inputLength == 1 && repeat <= PAD_LIMIT) {

6155            return repeat(str.charAt(0),repeat);

6156       }

6157

6158       final int outputLength = inputLength * repeat;

6159       switch (inputLength) {

6160            case 1 :

6161                return repeat(str.charAt(0),repeat);

6162            case 2 :

6163                final char ch0 = str.charAt(0);

6164                final char ch1 = str.charAt(1);

6165                final char[] output2 = newchar[outputLength];

6166                for (int i = repeat * 2 - 2; i>= 0; i--, i--) {

6167                    output2[i] = ch0;

6168                    output2[i + 1] = ch1;

6169                }

6170                return new String(output2);

6171            default :

6172               final StringBuilder buf= new StringBuilder(outputLength);

6173                for (int i = 0; i < repeat;i++) {

6174                    buf.append(str);

6175                }

6176                return buf.toString();

6177       }

6178   }

6179

6180   /**

6181    * <p>Repeat a String {@code repeat} times to form a

6182    * new String, with a String separator injected each time. </p>

6183    *

6184    * <pre>

6185    * StringUtils.repeat(null, null, 2) = null

6186    * StringUtils.repeat(null, "x", 2)  = null

6187    * StringUtils.repeat("", null, 0)   = ""

6188    * StringUtils.repeat("", "", 2)     = ""

6189    * StringUtils.repeat("", "x", 3)    = "xxx"

6190    * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"

6191    * </pre>

6192    *

6193    * @param str        the String torepeat, may be null

6194    * @param separator  the String toinject, may be null

6195    * @param repeat     number oftimes to repeat str, negative treated as zero

6196    * @return a new String consisting of the original String repeated,

6197    *  {@code null} if null Stringinput

6198    * @since 2.5

6199    */

6200   public static String repeat(final String str, final String separator,final int repeat) {

6201       if(str == null || separator == null) {

6202            return repeat(str, repeat);

6203       }

6204       // given that repeat(String, int) is quite optimized, better to rely onit than try and splice this into it

6205       final String result = repeat(str + separator, repeat);

6206       return removeEnd(result, separator);

6207   }

6208

6209   /**

6210    * <p>Returns padding using the specified delimiter repeated

6211    * to a given length.</p>

6212    *

6213    * <pre>

6214    * StringUtils.repeat('e', 0)  =""

6215    * StringUtils.repeat('e', 3)  ="eee"

6216    * StringUtils.repeat('e', -2) = ""

6217    * </pre>

6218    *

6219    * <p>Note: this method doesn't not support padding with

6220    * <ahref="http://www.unicode.org/glossary/#supplementary_character">UnicodeSupplementary Characters</a>

6221    * as they require a pair of {@code char}s to be represented.

6222    * If you are needing to support full I18N of your applications

6223    * consider using {@link #repeat(String, int)} instead.

6224    * </p>

6225    *

6226    * @param ch  character to repeat

6227    * @param repeat  number of timesto repeat char, negative treated as zero

6228    * @return String with repeated character

6229    * @see #repeat(String, int)

6230    */

6231   public static String repeat(final char ch, final int repeat) {

6232       if (repeat <= 0) {

6233            return EMPTY;

6234       }

6235       final char[] buf = new char[repeat];

6236       for (int i = repeat - 1; i >= 0; i--) {

6237            buf[i] = ch;

6238       }

6239       return new String(buf);

6240   }

6241

6242   /**

6243    * <p>Right pad a String with spaces (' ').</p>

6244    *

6245    * <p>The String is padded to the size of {@code size}.</p>

6246    *

6247    * <pre>

6248    * StringUtils.rightPad(null, *)  = null

6249    * StringUtils.rightPad("", 3)     = "  "

6250    * StringUtils.rightPad("bat", 3)  = "bat"

6251    * StringUtils.rightPad("bat", 5)  = "bat "

6252    * StringUtils.rightPad("bat", 1)  = "bat"

6253    * StringUtils.rightPad("bat", -1) = "bat"

6254    * </pre>

6255    *

6256    * @param str  the String to padout, may be null

6257    * @param size  the size to pad to

6258    * @return right padded String or original String if no padding isnecessary,

6259    *  {@code null} if null Stringinput

6260    */

6261   public static String rightPad(final String str, final int size) {

6262       return rightPad(str, size, ' ');

6263   }

6264

6265   /**

6266    * <p>Right pad a String with a specified character.</p>

6267    *

6268    * <p>The String is padded to the size of {@code size}.</p>

6269    *

6270    * <pre>

6271    * StringUtils.rightPad(null, *, *)    = null

6272    * StringUtils.rightPad("", 3, 'z')     = "zzz"

6273    * StringUtils.rightPad("bat", 3, 'z')  = "bat"

6274    * StringUtils.rightPad("bat", 5, 'z')  = "batzz"

6275    * StringUtils.rightPad("bat", 1, 'z')  = "bat"

6276    * StringUtils.rightPad("bat", -1, 'z') = "bat"

6277    * </pre>

6278    *

6279    * @param str  the String to padout, may be null

6280    * @param size  the size to pad to

6281    * @param padChar  the character topad with

6282    * @return right padded String or original String if no padding isnecessary,

6283    *  {@code null} if null Stringinput

6284    * @since 2.0

6285    */

6286   public static String rightPad(final String str, final int size, finalchar padChar) {

6287       if (str == null) {

6288            return null;

6289       }

6290       final int pads = size - str.length();

6291       if (pads <= 0) {

6292            return str; // returns originalString when possible

6293       }

6294       if (pads > PAD_LIMIT) {

6295            return rightPad(str, size,String.valueOf(padChar));

6296       }

6297       return str.concat(repeat(padChar, pads));

6298   }

6299

6300   /**

6301    * <p>Right pad a String with a specified String.</p>

6302    *

6303    * <p>The String is padded to the size of {@code size}.</p>

6304    *

6305    * <pre>

6306    * StringUtils.rightPad(null, *, *)     = null

6307    * StringUtils.rightPad("", 3, "z")      = "zzz"

6308    * StringUtils.rightPad("bat", 3, "yz")  = "bat"

6309    * StringUtils.rightPad("bat", 5, "yz")  = "batyz"

6310    * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"

6311    * StringUtils.rightPad("bat", 1, "yz")  = "bat"

6312    * StringUtils.rightPad("bat", -1, "yz") ="bat"

6313    * StringUtils.rightPad("bat", 5, null)  = "bat "

6314    * StringUtils.rightPad("bat", 5, "")    = "bat "

6315    * </pre>

6316    *

6317    * @param str  the String to padout, may be null

6318    * @param size  the size to pad to

6319    * @param padStr  the String to padwith, null or empty treated as single space

6320    * @return right padded String or original String if no padding isnecessary,

6321    *  {@code null} if null Stringinput

6322    */

6323   public static String rightPad(final String str, final int size, StringpadStr) {

6324       if (str == null) {

6325            return null;

6326       }

6327       if (isEmpty(padStr)) {

6328            padStr = SPACE;

6329       }

6330       final int padLen = padStr.length();

6331       final int strLen = str.length();

6332       final int pads = size - strLen;

6333       if (pads <= 0) {

6334            return str; // returns originalString when possible

6335       }

6336       if (padLen == 1 && pads <= PAD_LIMIT) {

6337            return rightPad(str, size,padStr.charAt(0));

6338       }

6339

6340       if (pads == padLen) {

6341            return str.concat(padStr);

6342       } else if (pads < padLen) {

6343            returnstr.concat(padStr.substring(0, pads));

6344       } else {

6345            final char[] padding = newchar[pads];

6346            final char[] padChars =padStr.toCharArray();

6347            for (int i = 0; i < pads; i++) {

6348               padding[i] = padChars[i% padLen];

6349            }

6350            return str.concat(newString(padding));

6351       }

6352   }

6353

6354   /**

6355    * <p>Left pad a String with spaces (' ').</p>

6356    *

6357    * <p>The String is padded to the size of {@code size}.</p>

6358    *

6359    * <pre>

6360    * StringUtils.leftPad(null, *)   =null

6361    * StringUtils.leftPad("", 3)     = "  "

6362    * StringUtils.leftPad("bat", 3)  = "bat"

6363    * StringUtils.leftPad("bat", 5)  = " bat"

6364    * StringUtils.leftPad("bat", 1)  = "bat"

6365    * StringUtils.leftPad("bat", -1) = "bat"

6366    * </pre>

6367    *

6368    * @param str  the String to padout, may be null

6369    * @param size  the size to pad to

6370    * @return left padded String or original String if no padding isnecessary,

6371    *  {@code null} if null Stringinput

6372    */

6373   public static String leftPad(final String str, final int size) {

6374       return leftPad(str, size, ' ');

6375   }

6376

6377   /**

6378    * <p>Left pad a String with a specified character.</p>

6379    *

6380    * <p>Pad to a size of {@code size}.</p>

6381    *

6382    * <pre>

6383    * StringUtils.leftPad(null, *, *)    = null

6384    * StringUtils.leftPad("", 3, 'z')     = "zzz"

6385    * StringUtils.leftPad("bat", 3, 'z')  = "bat"

6386    * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"

6387    * StringUtils.leftPad("bat", 1, 'z')  = "bat"

6388    * StringUtils.leftPad("bat", -1, 'z') = "bat"

6389    * </pre>

6390    *

6391    * @param str  the String to padout, may be null

6392    * @param size  the size to pad to

6393    * @param padChar  the character topad with

6394    * @return left padded String or original String if no padding isnecessary,

6395    *  {@code null} if null Stringinput

6396    * @since 2.0

6397    */

6398   public static String leftPad(final String str, final int size, finalchar padChar) {

6399       if (str == null) {

6400            return null;

6401       }

6402       final int pads = size - str.length();

6403       if (pads <= 0) {

6404            return str; // returns originalString when possible

6405       }

6406       if (pads > PAD_LIMIT) {

6407            return leftPad(str, size,String.valueOf(padChar));

6408       }

6409       return repeat(padChar, pads).concat(str);

6410   }

6411

6412   /**

6413    * <p>Left pad a String with a specified String.</p>

6414    *

6415    * <p>Pad to a size of{@code size}.</p>

6416    *

6417    * <pre>

6418    * StringUtils.leftPad(null, *, *)     = null

6419    * StringUtils.leftPad("", 3, "z")      = "zzz"

6420    * StringUtils.leftPad("bat", 3, "yz")  = "bat"

6421    * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"

6422    * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"

6423    * StringUtils.leftPad("bat", 1, "yz")  = "bat"

6424    * StringUtils.leftPad("bat", -1, "yz") ="bat"

6425    * StringUtils.leftPad("bat", 5, null)  = " bat"

6426    * StringUtils.leftPad("bat", 5, "")    = " bat"

6427    * </pre>

6428    *

6429    * @param str  the String to padout, may be null

6430    * @param size  the size to pad to

6431    * @param padStr  the String to padwith, null or empty treated as single space

6432    * @return left padded String or original String if no padding isnecessary,

6433    *  {@code null} if null Stringinput

6434    */

6435   public static String leftPad(final String str, final int size, StringpadStr) {

6436       if (str == null) {

6437            return null;

6438       }

6439       if (isEmpty(padStr)) {

6440            padStr = SPACE;

6441       }

6442       final int padLen = padStr.length();

6443       final int strLen = str.length();

6444       final int pads = size - strLen;

6445       if (pads <= 0) {

6446            return str; // returns originalString when possible

6447       }

6448       if (padLen == 1 && pads <= PAD_LIMIT) {

6449            return leftPad(str, size,padStr.charAt(0));

6450       }

6451

6452       if (pads == padLen) {

6453            return padStr.concat(str);

6454       } else if (pads < padLen) {

6455            return padStr.substring(0,pads).concat(str);

6456       } else {

6457            final char[] padding = newchar[pads];

6458            final char[] padChars =padStr.toCharArray();

6459            for (int i = 0; i < pads; i++) {

6460               padding[i] = padChars[i %padLen];

6461            }

6462            return newString(padding).concat(str);

6463       }

6464   }

6465

6466   /**

6467    * Gets a CharSequence length or {@code 0} if the CharSequence is

6468    * {@code null}.

6469    *

6470    * @param cs

6471    *            a CharSequence or{@code null}

6472    * @return CharSequence length or {@code 0} if the CharSequence is

6473    *         {@code null}.

6474    * @since 2.4

6475    * @since 3.0 Changed signature from length(String) tolength(CharSequence)

6476    */

6477   public static int length(final CharSequence cs) {

6478       return cs == null ? 0 : cs.length();

6479   }

6480

6481   // Centering

6482   //-----------------------------------------------------------------------

6483   /**

6484    * <p>Centers a String in a larger String of size {@code size}

6485    * using the space character (' ').</p>

6486    *

6487    * <p>If the size is less than the String length, the String isreturned.

6488    * A {@code null} String returns {@code null}.

6489    * A negative size is treated as zero.</p>

6490    *

6491    * <p>Equivalent to {@code center(str, size, "")}.</p>

6492    *

6493    * <pre>

6494    * StringUtils.center(null, *)   =null

6495    * StringUtils.center("", 4)    = "    "

6496    * StringUtils.center("ab", -1) = "ab"

6497    * StringUtils.center("ab", 4)  = " ab "

6498    * StringUtils.center("abcd", 2) = "abcd"

6499    * StringUtils.center("a", 4)   = " a  "

6500    * </pre>

6501    *

6502    * @param str  the String tocenter, may be null

6503    * @param size  the int size of newString, negative treated as zero

6504    * @return centered String, {@code null} if null String input

6505    */

6506   public static String center(final String str, final int size) {

6507       return center(str, size, ' ');

6508   }

6509

6510   /**

6511    * <p>Centers a String in a larger String of size {@code size}.

6512    * Uses a supplied character asthe value to pad the String with.</p>

6513    *

6514    * <p>If the size is less than the String length, the String isreturned.

6515    * A {@code null} String returns {@code null}.

6516    * A negative size is treated as zero.</p>

6517    *

6518    * <pre>

6519    * StringUtils.center(null, *, *)    = null

6520    * StringUtils.center("", 4, ' ')     = "   "

6521    * StringUtils.center("ab", -1, ' ')  = "ab"

6522    * StringUtils.center("ab", 4, ' ')   = " ab "

6523    * StringUtils.center("abcd", 2, ' ') = "abcd"

6524    * StringUtils.center("a", 4, ' ')    = " a "

6525    * StringUtils.center("a", 4, 'y')    = "yayy"

6526    * </pre>

6527    *

6528    * @param str  the String tocenter, may be null

6529    * @param size  the int size of newString, negative treated as zero

6530    * @param padChar  the character topad the new String with

6531    * @return centered String, {@code null} if null String input

6532    * @since 2.0

6533    */

6534   public static String center(String str, final int size, final charpadChar) {

6535       if (str == null || size <= 0) {

6536            return str;

6537       }

6538       final int strLen = str.length();

6539       final int pads = size - strLen;

6540       if (pads <= 0) {

6541            return str;

6542       }

6543       str = leftPad(str, strLen + pads / 2, padChar);

6544       str = rightPad(str, size, padChar);

6545       return str;

6546   }

6547

6548   /**

6549    * <p>Centers a String in a larger String of size {@code size}.

6550    * Uses a supplied String as the value to pad the String with.</p>

6551    *

6552    * <p>If the size is less than the String length, the String isreturned.

6553    * A {@code null} String returns {@code null}.

6554    * A negative size is treated as zero.</p>

6555    *

6556    * <pre>

6557    * StringUtils.center(null, *, *)    = null

6558    * StringUtils.center("", 4, " ")     = "   "

6559    * StringUtils.center("ab", -1, " ")  = "ab"

6560    * StringUtils.center("ab", 4, " ")   = " ab "

6561    * StringUtils.center("abcd", 2, " ") ="abcd"

6562    * StringUtils.center("a", 4, " ")    = " a "

6563    * StringUtils.center("a", 4, "yz")   = "yayz"

6564    * StringUtils.center("abc", 7, null) = "  abc "

6565    * StringUtils.center("abc", 7, "")   = " abc  "

6566    * </pre>

6567    *

6568    * @param str  the String tocenter, may be null

6569    * @param size  the int size of newString, negative treated as zero

6570    * @param padStr  the String to padthe new String with, must not be null or empty

6571    * @return centered String, {@code null} if null String input

6572    * @throws IllegalArgumentException if padStr is {@code null} or empty

6573    */

6574   public static String center(String str, final int size, String padStr) {

6575       if (str == null || size <= 0) {

6576            return str;

6577       }

6578       if (isEmpty(padStr)) {

6579            padStr = SPACE;

6580       }

6581       final int strLen = str.length();

6582       final int pads = size - strLen;

6583       if (pads <= 0) {

6584            return str;

6585       }

6586       str = leftPad(str, strLen + pads / 2, padStr);

6587       str = rightPad(str, size, padStr);

6588       return str;

6589   }

6590

6591   // Case conversion

6592   //-----------------------------------------------------------------------

6593   /**

6594    * <p>Converts a String to upper case as per {@linkString#toUpperCase()}.</p>

6595    *

6596    * <p>A {@code null} input String returns {@code null}.</p>

6597    *

6598    * <pre>

6599    * StringUtils.upperCase(null)  =null

6600    * StringUtils.upperCase("")   = ""

6601    * StringUtils.upperCase("aBc") = "ABC"

6602    * </pre>

6603    *

6604    * <p><strong>Note:</strong> As described in thedocumentation for {@link String#toUpperCase()},

6605    * the result of this method is affected by the current locale.

6606    * For platform-independent case transformations, the method {@link#lowerCase(String, Locale)}

6607    * should be used with a specific locale (e.g. {@linkLocale#ENGLISH}).</p>

6608    *

6609    * @param str  the String to uppercase, may be null

6610    * @return the upper cased String, {@code null} if null String input

6611    */

6612   public static String upperCase(final String str) {

6613       if (str == null) {

6614            return null;

6615        }

6616       return str.toUpperCase();

6617   }

6618

6619   /**

6620    * <p>Converts a String to upper case as per {@linkString#toUpperCase(Locale)}.</p>

6621    *

6622    * <p>A {@code null} input String returns {@code null}.</p>

6623    *

6624    * <pre>

6625    * StringUtils.upperCase(null, Locale.ENGLISH)  = null

6626    * StringUtils.upperCase("", Locale.ENGLISH)    = ""

6627    * StringUtils.upperCase("aBc", Locale.ENGLISH) ="ABC"

6628    * </pre>

6629    *

6630    * @param str  the String to uppercase, may be null

6631    * @param locale  the locale thatdefines the case transformation rules, must not be null

6632    * @return the upper cased String, {@code null} if null String input

6633    * @since 2.5

6634    */

6635   public static StringupperCase(final String str, final Locale locale) {

6636       if (str == null) {

6637            return null;

6638       }

6639       return str.toUpperCase(locale);

6640   }

6641

6642   /**

6643    * <p>Converts a String to lower case as per {@linkString#toLowerCase()}.</p>

6644    *

6645    * <p>A {@code null} input String returns {@code null}.</p>

6646    *

6647    * <pre>

6648    * StringUtils.lowerCase(null)  =null

6649    * StringUtils.lowerCase("")   = ""

6650    * StringUtils.lowerCase("aBc") = "abc"

6651    * </pre>

6652    *

6653    * <p><strong>Note:</strong> As described in thedocumentation for {@link String#toLowerCase()},

6654    * the result of this method is affected by the current locale.

6655    * For platform-independent case transformations, the method {@link#lowerCase(String, Locale)}

6656    * should be used with a specific locale (e.g. {@linkLocale#ENGLISH}).</p>

6657    *

6658    * @param str  the String to lower case,may be null

6659    * @return the lower cased String, {@code null} if null String input

6660    */

6661   public static String lowerCase(final String str) {

6662       if (str == null) {

6663            return null;

6664       }

6665       return str.toLowerCase();

6666   }

6667

6668   /**

6669    * <p>Converts a String to lower case as per {@linkString#toLowerCase(Locale)}.</p>

6670    *

6671    * <p>A {@code null} input String returns {@code null}.</p>

6672    *

6673    * <pre>

6674    * StringUtils.lowerCase(null, Locale.ENGLISH)  = null

6675    * StringUtils.lowerCase("", Locale.ENGLISH)    = ""

6676    * StringUtils.lowerCase("aBc", Locale.ENGLISH) ="abc"

6677    * </pre>

6678    *

6679    * @param str  the String to lowercase, may be null

6680    * @param locale  the locale thatdefines the case transformation rules, must not be null

6681    * @return the lower cased String, {@code null} if null String input

6682    * @since 2.5

6683    */

6684   public static String lowerCase(final String str, final Locale locale) {

6685       if (str == null) {

6686            return null;

6687       }

6688       return str.toLowerCase(locale);

6689   }

6690

6691   /**

6692    * <p>Capitalizes a String changing the first character to titlecase as

6693    * per {@link Character#toTitleCase(int)}. No other characters arechanged.</p>

6694    *

6695    * <p>For a word based algorithm, see {@linkorg.apache.commons.lang3.text.WordUtils#capitalize(String)}.

6696    * A {@code null} input String returns {@code null}.</p>

6697    *

6698    * <pre>

6699    * StringUtils.capitalize(null)  =null

6700    * StringUtils.capitalize("")   = ""

6701    * StringUtils.capitalize("cat") = "Cat"

6702    * StringUtils.capitalize("cAt") = "CAt"

6703    * StringUtils.capitalize("'cat'") = "'cat'"

6704    * </pre>

6705    *

6706    * @param str the String to capitalize, may be null

6707    * @return the capitalized String, {@code null} if null String input

6708    * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)

6709    * @see #uncapitalize(String)

6710    * @since 2.0

6711    */

6712   public static String capitalize(final String str) {

6713       int strLen;

6714       if (str == null || (strLen = str.length()) == 0) {

6715            return str;

6716       }

6717

6718       final int firstCodepoint = str.codePointAt(0);

6719       final int newCodePoint = Character.toTitleCase(firstCodepoint);

6720       if (firstCodepoint == newCodePoint) {

6721            // already capitalized

6722            return str;

6723       }

6724

6725       final int newCodePoints[] = new int[strLen]; // cannot be longer thanthe char array

6726       int outOffset = 0;

6727       newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint

6728       for (int inOffset = Character.charCount(firstCodepoint); inOffset <strLen; ) {

6729            final int codepoint =str.codePointAt(inOffset);

6730            newCodePoints[outOffset++] =codepoint; // copy the remaining ones

6731            inOffset +=Character.charCount(codepoint);

6732        }

6733       return new String(newCodePoints, 0, outOffset);

6734   }

6735

6736   /**

6737    * <p>Uncapitalizes a String, changing the first character to lowercase as

6738    * per {@link Character#toLowerCase(int)}. No other characters arechanged.</p>

6739    *

6740    * <p>For a word based algorithm, see {@linkorg.apache.commons.lang3.text.WordUtils#uncapitalize(String)}.

6741    * A {@code null} input String returns {@code null}.</p>

6742    *

6743    * <pre>

6744    * StringUtils.uncapitalize(null) = null

6745    * StringUtils.uncapitalize("")    = ""

6746    * StringUtils.uncapitalize("cat") = "cat"

6747    * StringUtils.uncapitalize("Cat") = "cat"

6748    * StringUtils.uncapitalize("CAT") = "cAT"

6749    * </pre>

6750    *

6751    * @param str the String to uncapitalize, may be null

6752    * @return the uncapitalized String, {@code null} if null String input

6753    * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String)

6754    * @see #capitalize(String)

6755    * @since 2.0

6756    */

6757   public static String uncapitalize(final String str) {

6758       int strLen;

6759       if (str == null || (strLen = str.length()) == 0) {

6760            return str;

6761       }

6762

6763       final int firstCodepoint = str.codePointAt(0);

6764       final int newCodePoint = Character.toLowerCase(firstCodepoint);

6765       if (firstCodepoint == newCodePoint) {

6766            // already capitalized

6767            return str;

6768       }

6769

6770       final int newCodePoints[] = new int[strLen]; // cannot be longer thanthe char array

6771       int outOffset = 0;

6772       newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint

6773       for (int inOffset = Character.charCount(firstCodepoint); inOffset <strLen; ) {

6774            final int codepoint =str.codePointAt(inOffset);

6775           newCodePoints[outOffset++]= codepoint; // copy the remaining ones

6776            inOffset +=Character.charCount(codepoint);

6777        }

6778       return new String(newCodePoints, 0, outOffset);

6779   }

6780

6781   /**

6782    * <p>Swaps the case of a String changing upper and title case to

6783    * lower case, and lower case to upper case.</p>

6784    *

6785    * <ul>

6786    *  <li>Upper case characterconverts to Lower case</li>

6787    *  <li>Title case characterconverts to Lower case</li>

6788    *  <li>Lower case characterconverts to Upper case</li>

6789    * </ul>

6790    *

6791    * <p>For a word based algorithm, see {@linkorg.apache.commons.lang3.text.WordUtils#swapCase(String)}.

6792    * A {@code null} input String returns {@code null}.</p>

6793    *

6794    * <pre>

6795    * StringUtils.swapCase(null)                 = null

6796    * StringUtils.swapCase("")                   = ""

6797    * StringUtils.swapCase("The dog has a BONE") = "tHE DOGHAS A bone"

6798    * </pre>

6799    *

6800    * <p>NOTE: This method changed in Lang version 2.0.

6801    * It no longer performs a word based algorithm.

6802    * If you only use ASCII, you will notice no change.

6803    * That functionality is available inorg.apache.commons.lang3.text.WordUtils.</p>

6804    *

6805    * @param str  the String to swapcase, may be null

6806    * @return the changed String, {@code null} if null String input

6807    */

6808   public static String swapCase(final String str) {

6809       if (StringUtils.isEmpty(str)) {

6810            return str;

6811       }

6812

6813       final int strLen = str.length();

6814       final int newCodePoints[] = new int[strLen]; // cannot be longer thanthe char array

6815       int outOffset = 0;

6816       for (int i = 0; i < strLen; ) {

6817            final int oldCodepoint =str.codePointAt(i);

6818            final int newCodePoint;

6819            if(Character.isUpperCase(oldCodepoint)) {

6820                newCodePoint =Character.toLowerCase(oldCodepoint);

6821            } else if(Character.isTitleCase(oldCodepoint)) {

6822                newCodePoint = Character.toLowerCase(oldCodepoint);

6823            } else if(Character.isLowerCase(oldCodepoint)) {

6824                newCodePoint =Character.toUpperCase(oldCodepoint);

6825            } else {

6826                newCodePoint = oldCodepoint;

6827            }

6828            newCodePoints[outOffset++] =newCodePoint;

6829            i +=Character.charCount(newCodePoint);

6830        }

6831       return new String(newCodePoints, 0, outOffset);

6832   }

6833

6834   // Count matches

6835   //-----------------------------------------------------------------------

6836   /**

6837    * <p>Counts how many times the substring appears in the largerstring.</p>

6838    *

6839    * <p>A {@code null} or empty ("") String input returns{@code 0}.</p>

6840    *

6841    * <pre>

6842    * StringUtils.countMatches(null, *)      = 0

6843    * StringUtils.countMatches("", *)         = 0

6844    * StringUtils.countMatches("abba", null)  = 0

6845    * StringUtils.countMatches("abba", "")    = 0

6846    * StringUtils.countMatches("abba", "a")   = 2

6847    * StringUtils.countMatches("abba", "ab")  = 1

6848    * StringUtils.countMatches("abba", "xxx") = 0

6849    * </pre>

6850    *

6851    * @param str  the CharSequence tocheck, may be null

6852    * @param sub  the substring tocount, may be null

6853    * @return the number of occurrences, 0 if either CharSequence is {@codenull}

6854    * @since 3.0 Changed signature from countMatches(String, String) tocountMatches(CharSequence, CharSequence)

6855    */

6856   public static int countMatches(final CharSequence str, finalCharSequence sub) {

6857       if (isEmpty(str) || isEmpty(sub)) {

6858            return 0;

6859       }

6860       int count = 0;

6861       int idx = 0;

6862       while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) !=INDEX_NOT_FOUND) {

6863            count++;

6864            idx += sub.length();

6865       }

6866       return count;

6867   }

6868

6869   /**

6870    * <p>Counts how many times the char appears in the givenstring.</p>

6871    *

6872    * <p>A {@code null} or empty ("") String input returns{@code 0}.</p>

6873    *

6874    * <pre>

6875    * StringUtils.countMatches(null, *)      = 0

6876    * StringUtils.countMatches("", *)         = 0

6877    * StringUtils.countMatches("abba", 0)  = 0

6878    * StringUtils.countMatches("abba", 'a')   = 2

6879    * StringUtils.countMatches("abba", 'b')  = 2

6880    * StringUtils.countMatches("abba", 'x') = 0

6881    * </pre>

6882    *

6883    * @param str  the CharSequence tocheck, may be null

6884    * @param ch  the char to count

6885    * @return the number of occurrences, 0 if the CharSequence is {@codenull}

6886    * @since 3.4

6887    */

6888   public static int countMatches(final CharSequence str, final char ch) {

6889       if (isEmpty(str)) {

6890            return 0;

6891       }

6892       int count = 0;

6893       // We could also call str.toCharArray() for faster look ups but that wouldgenerate more garbage.

6894       for (int i = 0; i < str.length(); i++) {

6895            if (ch == str.charAt(i)) {

6896                count++;

6897            }

6898       }

6899       return count;

6900   }

6901

6902   // Character Tests

6903   //-----------------------------------------------------------------------

6904   /**

6905    * <p>Checks if the CharSequence contains only Unicodeletters.</p>

6906    *

6907    * <p>{@code null} will return {@code false}.

6908    * An empty CharSequence (length()=0) will return {@codefalse}.</p>

6909    *

6910    * <pre>

6911    * StringUtils.isAlpha(null)   =false

6912    * StringUtils.isAlpha("")    = false

6913    * StringUtils.isAlpha(" ")   = false

6914    * StringUtils.isAlpha("abc") = true

6915    * StringUtils.isAlpha("ab2c") = false

6916    * StringUtils.isAlpha("ab-c") = false

6917    * </pre>

6918    *

6919    * @param cs  the CharSequence tocheck, may be null

6920    * @return {@code true} if only contains letters, and is non-null

6921    * @since 3.0 Changed signature from isAlpha(String) toisAlpha(CharSequence)

6922    * @since 3.0 Changed "" to return false and not true

6923    */

6924   public static boolean isAlpha(final CharSequence cs) {

6925       if (isEmpty(cs)) {

6926            return false;

6927       }

6928       final int sz = cs.length();

6929       for (int i = 0; i < sz; i++) {

6930            if(Character.isLetter(cs.charAt(i)) == false) {

6931                return false;

6932            }

6933       }

6934       return true;

6935   }

6936

6937   /**

6938    * <p>Checks if the CharSequence contains only Unicode letters and

6939    * space (' ').</p>

6940    *

6941    * <p>{@code null} will return {@code false}

6942    * An empty CharSequence (length()=0) will return {@code true}.</p>

6943    *

6944    * <pre>

6945    * StringUtils.isAlphaSpace(null)  = false

6946    * StringUtils.isAlphaSpace("")     = true

6947    * StringUtils.isAlphaSpace(" ")   = true

6948    * StringUtils.isAlphaSpace("abc")  = true

6949    * StringUtils.isAlphaSpace("ab c") = true

6950    * StringUtils.isAlphaSpace("ab2c") = false

6951    * StringUtils.isAlphaSpace("ab-c") = false

6952    * </pre>

6953    *

6954    * @param cs  the CharSequence tocheck, may be null

6955    * @return {@code true} if only contains letters and space,

6956    *  and is non-null

6957    * @since 3.0 Changed signature from isAlphaSpace(String) toisAlphaSpace(CharSequence)

6958    */

6959   public static boolean isAlphaSpace(final CharSequence cs) {

6960       if (cs == null) {

6961            return false;

6962       }

6963       final int sz = cs.length();

6964       for (int i = 0; i < sz; i++) {

6965            if (Character.isLetter(cs.charAt(i)) == false&& cs.charAt(i) != ' ') {

6966                return false;

6967            }

6968       }

6969       return true;

6970   }

6971

6972   /**

6973    * <p>Checks if the CharSequence contains only Unicode letters ordigits.</p>

6974    *

6975    * <p>{@code null} will return {@code false}.

6976    * An empty CharSequence (length()=0) will return {@codefalse}.</p>

6977    *

6978    * <pre>

6979    * StringUtils.isAlphanumeric(null)  = false

6980    * StringUtils.isAlphanumeric("")     = false

6981    * StringUtils.isAlphanumeric(" ")   = false

6982    * StringUtils.isAlphanumeric("abc")  = true

6983    * StringUtils.isAlphanumeric("ab c") = false

6984    * StringUtils.isAlphanumeric("ab2c") = true

6985    * StringUtils.isAlphanumeric("ab-c") = false

6986    * </pre>

6987    *

6988    * @param cs  the CharSequence tocheck, may be null

6989    * @return {@code true} if only contains letters or digits,

6990    *  and is non-null

6991    * @since 3.0 Changed signature from isAlphanumeric(String) toisAlphanumeric(CharSequence)

6992    * @since 3.0 Changed "" to return false and not true

6993    */

6994   public static boolean isAlphanumeric(final CharSequence cs) {

6995       if (isEmpty(cs)) {

6996            return false;

6997       }

6998       final int sz = cs.length();

6999       for (int i = 0; i < sz; i++) {

7000            if(Character.isLetterOrDigit(cs.charAt(i)) == false) {

7001                return false;

7002            }

7003       }

7004       return true;

7005   }

7006

7007   /**

7008    * <p>Checks if the CharSequence contains only Unicode letters,digits

7009    * or space ({@code ' '}).</p>

7010    *

7011    * <p>{@code null} will return {@code false}.

7012    * An empty CharSequence (length()=0) will return {@code true}.</p>

7013    *

7014    * <pre>

7015    * StringUtils.isAlphanumericSpace(null)  = false

7016    * StringUtils.isAlphanumericSpace("")     = true

7017    * StringUtils.isAlphanumericSpace(" ")   = true

7018    * StringUtils.isAlphanumericSpace("abc")  = true

7019    * StringUtils.isAlphanumericSpace("ab c") = true

7020    * StringUtils.isAlphanumericSpace("ab2c") = true

7021     *StringUtils.isAlphanumericSpace("ab-c") = false

7022    * </pre>

7023    *

7024    * @param cs  the CharSequence tocheck, may be null

7025    * @return {@code true} if only contains letters, digits or space,

7026    *  and is non-null

7027    * @since 3.0 Changed signature from isAlphanumericSpace(String) toisAlphanumericSpace(CharSequence)

7028    */

7029   public static boolean isAlphanumericSpace(final CharSequence cs) {

7030       if (cs == null) {

7031            return false;

7032       }

7033       final int sz = cs.length();

7034       for (int i = 0; i < sz; i++) {

7035            if(Character.isLetterOrDigit(cs.charAt(i)) == false && cs.charAt(i) != '') {

7036                return false;

7037            }

7038       }

7039       return true;

7040   }

7041

7042   /**

7043    * <p>Checks if the CharSequence contains only ASCII printablecharacters.</p>

7044    *

7045    * <p>{@code null} will return {@code false}.

7046    * An empty CharSequence (length()=0) will return {@code true}.</p>

7047    *

7048    * <pre>

7049    * StringUtils.isAsciiPrintable(null)    = false

7050    * StringUtils.isAsciiPrintable("")       = true

7051    * StringUtils.isAsciiPrintable(" ")      = true

7052    * StringUtils.isAsciiPrintable("Ceki")   = true

7053    * StringUtils.isAsciiPrintable("ab2c")   = true

7054    * StringUtils.isAsciiPrintable("!ab-c~") = true

7055    * StringUtils.isAsciiPrintable("\u0020") = true

7056    * StringUtils.isAsciiPrintable("\u0021") = true

7057    * StringUtils.isAsciiPrintable("\u007e") = true

7058    * StringUtils.isAsciiPrintable("\u007f") = false

7059    * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false

7060    * </pre>

7061    *

7062    * @param cs the CharSequence to check, may be null

7063    * @return {@code true} if every character is in the range

7064    *  32 thru 126

7065    * @since 2.1

7066    * @since 3.0 Changed signature from isAsciiPrintable(String) toisAsciiPrintable(CharSequence)

7067    */

7068   public static boolean isAsciiPrintable(final CharSequence cs) {

7069       if (cs == null) {

7070            return false;

7071       }

7072       final int sz = cs.length();

7073       for (int i = 0; i < sz; i++) {

7074            if(CharUtils.isAsciiPrintable(cs.charAt(i)) == false) {

7075                return false;

7076            }

7077       }

7078       return true;

7079   }

7080

7081   /**

7082    * <p>Checks if the CharSequence contains only Unicode digits.

7083    * A decimal point is not a Unicode digit and returns false.</p>

7084    *

7085    * <p>{@code null} will return {@code false}.

7086    * An empty CharSequence (length()=0) will return {@codefalse}.</p>

7087    *

7088    * <p>Note that the method does not allow for a leading sign,either positive or negative.

7089    * Also, if a String passes the numeric test, it may still generate aNumberFormatException

7090    * when parsed by Integer.parseInt or Long.parseLong, e.g. if the valueis outside the range

7091    * for int or long respectively.</p>

7092    *

7093    * <pre>

7094    * StringUtils.isNumeric(null)   =false

7095    * StringUtils.isNumeric("")    = false

7096    * StringUtils.isNumeric(" ")   = false

7097    * StringUtils.isNumeric("123") = true

7098    * StringUtils.isNumeric("\u0967\u0968\u0969")  = true

7099    * StringUtils.isNumeric("12 3") = false

7100    * StringUtils.isNumeric("ab2c") = false

7101    * StringUtils.isNumeric("12-3") = false

7102    * StringUtils.isNumeric("12.3") = false

7103    * StringUtils.isNumeric("-123") = false

7104    * StringUtils.isNumeric("+123") = false

7105    * </pre>

7106    *

7107    * @param cs  the CharSequence tocheck, may be null

7108    * @return {@code true} if only contains digits, and is non-null

7109    * @since 3.0 Changed signature from isNumeric(String) toisNumeric(CharSequence)

7110    * @since 3.0 Changed "" to return false and not true

7111    */

7112   public static boolean isNumeric(final CharSequence cs) {

7113       if (isEmpty(cs)) {

7114            return false;

7115       }

7116       final int sz = cs.length();

7117       for (int i = 0; i < sz; i++) {

7118            if(!Character.isDigit(cs.charAt(i))) {

7119                return false;

7120            }

7121       }

7122       return true;

7123   }

7124

7125   /**

7126    * <p>Checks if the CharSequence contains only Unicode digits orspace

7127    * ({@code ' '}).

7128    * A decimal point is not a Unicode digit and returns false.</p>

7129    *

7130    * <p>{@code null} will return {@code false}.

7131    * An empty CharSequence (length()=0) will return {@code true}.</p>

7132    *

7133    * <pre>

7134    * StringUtils.isNumericSpace(null)  = false

7135    * StringUtils.isNumericSpace("")     = true

7136    * StringUtils.isNumericSpace(" ")   = true

7137    * StringUtils.isNumericSpace("123")  = true

7138    * StringUtils.isNumericSpace("12 3") = true

7139    * StringUtils.isNumeric("\u0967\u0968\u0969")  = true

7140    * StringUtils.isNumeric("\u0967\u0968 \u0969")  = true

7141    * StringUtils.isNumericSpace("ab2c") = false

7142    * StringUtils.isNumericSpace("12-3") = false

7143    * StringUtils.isNumericSpace("12.3") = false

7144    * </pre>

7145    *

7146    * @param cs  the CharSequence tocheck, may be null

7147    * @return {@code true} if only contains digits or space,

7148    *  and is non-null

7149    * @since 3.0 Changed signature from isNumericSpace(String) toisNumericSpace(CharSequence)

7150    */

7151   public static boolean isNumericSpace(final CharSequence cs) {

7152       if (cs == null) {

7153            return false;

7154       }

7155       final int sz = cs.length();

7156       for (int i = 0; i < sz; i++) {

7157            if (Character.isDigit(cs.charAt(i))== false && cs.charAt(i) != ' ') {

7158                return false;

7159            }

7160       }

7161       return true;

7162   }

7163

7164   /**

7165    * <p>Checks if a String {@code str} contains Unicode digits,

7166    * if yes then concatenate all the digits in {@code str} and return it asa String.</p>

7167    *

7168    * <p>An empty ("") String will be returned if no digitsfound in {@code str}.</p>

7169    *

7170    * <pre>

7171    * StringUtils.getDigits(null)  =null

7172    * StringUtils.getDigits("")   = ""

7173    * StringUtils.getDigits("abc") = ""

7174    * StringUtils.getDigits("1000$") = "1000"

7175    * StringUtils.getDigits("1123~45") = "12345"

7176    * StringUtils.getDigits("(541) 754-3010") ="5417543010"

7177    * StringUtils.getDigits("\u0967\u0968\u0969") ="\u0967\u0968\u0969"

7178    * </pre>

7179    *

7180    * @param str the String to extract digits from, may be null

7181    * @return String with only digits,

7182    *           or an empty("") String if no digits found,

7183    *           or {@code null} Stringif {@code str} is null

7184    * @since 3.6

7185    */

7186    public static String getDigits(final Stringstr) {

7187       if (isEmpty(str)) {

7188            return str;

7189       }

7190       final int sz = str.length();

7191       final StringBuilder strDigits = new StringBuilder(sz);

7192       for (int i = 0; i < sz; i++) {

7193            final char tempChar =str.charAt(i);

7194            if (Character.isDigit(tempChar)) {

7195                strDigits.append(tempChar);

7196            }

7197       }

7198       return strDigits.toString();

7199   }

7200

7201   /**

7202    * <p>Checks if the CharSequence contains onlywhitespace.</p>

7203    *

7204    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

7205    *

7206    * <p>{@code null} will return {@code false}.

7207    * An empty CharSequence (length()=0) will return {@code true}.</p>

7208    *

7209    * <pre>

7210    * StringUtils.isWhitespace(null)  = false

7211    * StringUtils.isWhitespace("")     = true

7212    * StringUtils.isWhitespace(" ")   = true

7213    *StringUtils.isWhitespace("abc") = false

7214    * StringUtils.isWhitespace("ab2c") = false

7215    * StringUtils.isWhitespace("ab-c") = false

7216    * </pre>

7217    *

7218    * @param cs  the CharSequence tocheck, may be null

7219    * @return {@code true} if only contains whitespace, and is non-null

7220    * @since 2.0

7221    * @since 3.0 Changed signature from isWhitespace(String) toisWhitespace(CharSequence)

7222    */

7223   public static boolean isWhitespace(final CharSequence cs) {

7224       if (cs == null) {

7225            return false;

7226       }

7227       final int sz = cs.length();

7228       for (int i = 0; i < sz; i++) {

7229            if(Character.isWhitespace(cs.charAt(i)) == false) {

7230                return false;

7231            }

7232       }

7233       return true;

7234   }

7235

7236   /**

7237    * <p>Checks if the CharSequence contains only lowercasecharacters.</p>

7238    *

7239    * <p>{@code null} will return {@code false}.

7240    * An empty CharSequence(length()=0) will return {@code false}.</p>

7241    *

7242    * <pre>

7243    * StringUtils.isAllLowerCase(null)  = false

7244    * StringUtils.isAllLowerCase("")     = false

7245    * StringUtils.isAllLowerCase(" ")   = false

7246    * StringUtils.isAllLowerCase("abc")  = true

7247    * StringUtils.isAllLowerCase("abC")  = false

7248    * StringUtils.isAllLowerCase("ab c") = false

7249    * StringUtils.isAllLowerCase("ab1c") = false

7250    * StringUtils.isAllLowerCase("ab/c") = false

7251    * </pre>

7252    *

7253    * @param cs  the CharSequence tocheck, may be null

7254    * @return {@code true} if only contains lowercase characters, and isnon-null

7255    * @since 2.5

7256    * @since 3.0 Changed signature from isAllLowerCase(String) toisAllLowerCase(CharSequence)

7257    */

7258   public static boolean isAllLowerCase(final CharSequence cs) {

7259       if (cs == null || isEmpty(cs)) {

7260           return false;

7261       }

7262       final int sz = cs.length();

7263       for (int i = 0; i < sz; i++) {

7264            if(Character.isLowerCase(cs.charAt(i)) == false) {

7265                return false;

7266            }

7267       }

7268       return true;

7269   }

7270

7271   /**

7272    * <p>Checks if the CharSequence contains only uppercasecharacters.</p>

7273    *

7274    * <p>{@code null} will return {@code false}.

7275    * An empty String (length()=0) will return {@code false}.</p>

7276    *

7277    * <pre>

7278    * StringUtils.isAllUpperCase(null)  = false

7279    * StringUtils.isAllUpperCase("")     = false

7280    * StringUtils.isAllUpperCase(" ")   = false

7281    * StringUtils.isAllUpperCase("ABC")  = true

7282    * StringUtils.isAllUpperCase("aBC")  = false

7283    * StringUtils.isAllUpperCase("A C")  = false

7284    * StringUtils.isAllUpperCase("A1C")  = false

7285    * StringUtils.isAllUpperCase("A/C")  = false

7286    * </pre>

7287    *

7288    * @param cs the CharSequence to check, may be null

7289    * @return {@code true} if only contains uppercase characters, and isnon-null

7290    * @since 2.5

7291    * @since 3.0 Changed signature from isAllUpperCase(String) toisAllUpperCase(CharSequence)

7292    */

7293   public static boolean isAllUpperCase(final CharSequence cs) {

7294       if (cs == null || isEmpty(cs)) {

7295            return false;

7296       }

7297       final int sz = cs.length();

7298       for (int i = 0; i < sz; i++) {

7299            if(Character.isUpperCase(cs.charAt(i)) == false) {

7300                return false;

7301            }

7302       }

7303       return true;

7304   }

7305

7306   /**

7307    * <p>Checks if the CharSequence contains mixed casing of bothuppercase and lowercase characters.</p>

7308    *

7309    * <p>{@code null} will return {@code false}. An empty CharSequence({@code length()=0}) will return

7310    * {@code false}.</p>

7311    *

7312    * <pre>

7313    * StringUtils.isMixedCase(null)   = false

7314    * StringUtils.isMixedCase("")      = false

7315    * StringUtils.isMixedCase("ABC")   = false

7316    * StringUtils.isMixedCase("abc")   = false

7317    * StringUtils.isMixedCase("aBc")   = true

7318    * StringUtils.isMixedCase("A c")   = true

7319    * StringUtils.isMixedCase("A1c")   = true

7320    * StringUtils.isMixedCase("a/C")   = true

7321    * StringUtils.isMixedCase("aC\t")  = true

7322    * </pre>

7323    *

7324    * @param cs the CharSequence to check, may be null

7325    * @return {@code true} if the CharSequence contains both uppercase andlowercase characters

7326    * @since 3.5

7327    */

7328   public static boolean isMixedCase(final CharSequence cs) {

7329       if (isEmpty(cs) || cs.length() == 1) {

7330            return false;

7331       }

7332       boolean containsUppercase = false;

7333       boolean containsLowercase = false;

7334       final int sz = cs.length();

7335       for (int i = 0; i < sz; i++) {

7336            if (containsUppercase &&containsLowercase) {

7337                return true;

7338            } else if(Character.isUpperCase(cs.charAt(i))) {

7339                containsUppercase = true;

7340            } else if(Character.isLowerCase(cs.charAt(i))) {

7341                containsLowercase = true;

7342            }

7343       }

7344       return containsUppercase && containsLowercase;

7345   }

7346

7347   // Defaults

7348   //-----------------------------------------------------------------------

7349   /**

7350    * <p>Returns either the passed in String,

7351    * or if the String is {@code null}, an empty String("").</p>

7352    *

7353    * <pre>

7354    * StringUtils.defaultString(null) = ""

7355    * StringUtils.defaultString("")    = ""

7356    * StringUtils.defaultString("bat") = "bat"

7357    * </pre>

7358    *

7359    * @see ObjectUtils#toString(Object)

7360    * @see String#valueOf(Object)

7361    * @param str  the String to check,may be null

7362    * @return the passed in String, or the empty String if it

7363    *  was {@code null}

7364    */

7365   public static String defaultString(final String str) {

7366       return str == null ? EMPTY : str;

7367   }

7368

7369   /**

7370    * <p>Returns either the passed in String, or if the String is

7371    * {@code null}, the value of {@code defaultStr}.</p>

7372    *

7373    * <pre>

7374    * StringUtils.defaultString(null, "NULL")  = "NULL"

7375    * StringUtils.defaultString("", "NULL")    = ""

7376    * StringUtils.defaultString("bat", "NULL") ="bat"

7377    * </pre>

7378    *

7379    * @see ObjectUtils#toString(Object,String)

7380    * @see String#valueOf(Object)

7381    * @param str  the String to check,may be null

7382    * @param defaultStr  the defaultString to return

7383    *  if the input is {@code null},may be null

7384    * @return the passed in String, or the default if it was {@code null}

7385    */

7386   public static String defaultString(final String str, final StringdefaultStr) {

7387       return str == null ? defaultStr : str;

7388   }

7389

7390   /**

7391    * <p>Returns either the passed in CharSequence, or if theCharSequence is

7392    * whitespace, empty("") or {@code null}, the value of {@code defaultStr}.</p>

7393    *

7394    * <p>Whitespace is defined by {@linkCharacter#isWhitespace(char)}.</p>

7395    *

7396    * <pre>

7397    * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"

7398    * StringUtils.defaultIfBlank("", "NULL")    = "NULL"

7399    * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"

7400    * StringUtils.defaultIfBlank("bat", "NULL") ="bat"

7401    * StringUtils.defaultIfBlank("", null)      = null

7402    * </pre>

7403    * @param <T> the specific kind of CharSequence

7404    * @param str the CharSequence to check, may be null

7405    * @param defaultStr  the defaultCharSequence to return

7406    *  if the input is whitespace,empty ("") or {@code null}, may be null

7407    * @return the passed in CharSequence, or the default

7408    * @see StringUtils#defaultString(String, String)

7409    */

7410   public static <T extends CharSequence> T defaultIfBlank(final Tstr, final T defaultStr) {

7411       return isBlank(str) ? defaultStr : str;

7412   }

7413

7414   /**

7415    * <p>Returns either the passed in CharSequence, or if theCharSequence is

7416    * empty or {@code null}, the value of {@code defaultStr}.</p>

7417    *

7418    * <pre>

7419    * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"

7420    * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"

7421    * StringUtils.defaultIfEmpty(" ", "NULL")   = " "

7422    * StringUtils.defaultIfEmpty("bat", "NULL") ="bat"

7423    * StringUtils.defaultIfEmpty("", null)      = null

7424    * </pre>

7425    * @param <T> the specific kind of CharSequence

7426    * @param str  the CharSequence tocheck, may be null

7427    * @param defaultStr  the defaultCharSequence to return

7428    *  if the input is empty("") or {@code null}, may be null

7429    * @return the passed in CharSequence, or the default

7430    * @see StringUtils#defaultString(String, String)

7431    */

7432   public static <T extends CharSequence> T defaultIfEmpty(final Tstr, final T defaultStr) {

7433       return isEmpty(str) ? defaultStr : str;

7434   }

7435

7436   // Rotating (circular shift)

7437   //-----------------------------------------------------------------------

7438   /**

7439    * <p>Rotate (circular shift) a String of {@code shift}characters.</p>

7440    * <ul>

7441    *  <li>If {@code shift >0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>

7442    *  <li>If {@code shift <0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>

7443    * </ul>

7444    *

7445    * <pre>

7446    * StringUtils.rotate(null, *)       = null

7447    * StringUtils.rotate("", *)          = ""

7448    * StringUtils.rotate("abcdefg", 0)   = "abcdefg"

7449    * StringUtils.rotate("abcdefg", 2)   = "fgabcde"

7450    * StringUtils.rotate("abcdefg", -2)  = "cdefgab"

7451    * StringUtils.rotate("abcdefg", 7)   = "abcdefg"

7452    * StringUtils.rotate("abcdefg", -7)  = "abcdefg"

7453    * StringUtils.rotate("abcdefg", 9)   = "fgabcde"

7454    *StringUtils.rotate("abcdefg", -9) = "cdefgab"

7455    * </pre>

7456    *

7457    * @param str  the String torotate, may be null

7458    * @param shift  number of time toshift (positive : right shift, negative : left shift)

7459    * @return the rotated String,

7460    *          or the original Stringif {@code shift == 0},

7461    *          or {@code null} if nullString input

7462    * @since 3.5

7463    */

7464   public static String rotate(final String str, final int shift) {

7465       if (str == null) {

7466            return null;

7467       }

7468

7469       final int strLen = str.length();

7470       if (shift == 0 || strLen == 0 || shift % strLen == 0) {

7471            return str;

7472       }

7473

7474       final StringBuilder builder = new StringBuilder(strLen);

7475       final int offset = - (shift % strLen);

7476       builder.append(substring(str, offset));

7477       builder.append(substring(str, 0, offset));

7478       return builder.toString();

7479   }

7480

7481   // Reversing

7482   //-----------------------------------------------------------------------

7483   /**

7484    * <p>Reverses a String as per {@linkStringBuilder#reverse()}.</p>

7485    *

7486    * <p>A {@code null} String returns {@code null}.</p>

7487    *

7488    * <pre>

7489    * StringUtils.reverse(null)  =null

7490    * StringUtils.reverse("")   = ""

7491     * StringUtils.reverse("bat") ="tab"

7492    * </pre>

7493    *

7494    * @param str  the String toreverse, may be null

7495    * @return the reversed String, {@code null} if null String input

7496    */

7497   public static String reverse(final String str) {

7498       if (str == null) {

7499            return null;

7500       }

7501       return new StringBuilder(str).reverse().toString();

7502   }

7503

7504   /**

7505    * <p>Reverses a String that is delimited by a specificcharacter.</p>

7506    *

7507    * <p>The Strings between the delimiters are not reversed.

7508    * Thus java.lang.String becomes String.lang.java (if the delimiter

7509    * is {@code '.'}).</p>

7510    *

7511    * <pre>

7512    * StringUtils.reverseDelimited(null, *)      = null

7513    * StringUtils.reverseDelimited("", *)        = ""

7514    * StringUtils.reverseDelimited("a.b.c", 'x') ="a.b.c"

7515    * StringUtils.reverseDelimited("a.b.c", ".") ="c.b.a"

7516    * </pre>

7517    *

7518    * @param str  the String toreverse, may be null

7519    * @param separatorChar  theseparator character to use

7520    * @return the reversed String, {@code null} if null String input

7521    * @since 2.0

7522    */

7523   public static String reverseDelimited(final String str, final charseparatorChar) {

7524       if (str == null) {

7525            return null;

7526       }

7527       // could implement manually, but simple way is to reuse other,

7528       // probably slower, methods.

7529       final String[] strs = split(str, separatorChar);

7530       ArrayUtils.reverse(strs);

7531       return join(strs, separatorChar);

7532   }

7533

7534   // Abbreviating

7535   //-----------------------------------------------------------------------

7536   /**

7537    * <p>Abbreviates a String using ellipses. This will turn

7538    * "Now is the time for all good men" into "Now is thetime for..."</p>

7539    *

7540    * <p>Specifically:</p>

7541    * <ul>

7542    *   <li>If the number ofcharacters in {@code str} is less than or equal to

7543    *       {@code maxWidth}, return{@code str}.</li>

7544    *   <li>Else abbreviate itto {@code (substring(str, 0, max-3) + "...")}.</li>

7545    *   <li>If {@code maxWidth}is less than {@code 4}, throw an

7546    *       {@codeIllegalArgumentException}.</li>

7547    *   <li>In no case will itreturn a String of length greater than

7548    *       {@codemaxWidth}.</li>

7549    * </ul>

7550    *

7551    * <pre>

7552    * StringUtils.abbreviate(null, *)     = null

7553    * StringUtils.abbreviate("", 4)        = ""

7554    * StringUtils.abbreviate("abcdefg", 6) = "abc..."

7555    * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"

7556    * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"

7557    * StringUtils.abbreviate("abcdefg", 4) = "a..."

7558    * StringUtils.abbreviate("abcdefg", 3) =IllegalArgumentException

7559    * </pre>

7560    *

7561    * @param str  the String to check,may be null

7562    * @param maxWidth  maximum lengthof result String, must be at least 4

7563    * @return abbreviated String, {@code null} if null String input

7564    * @throws IllegalArgumentException if the width is too small

7565    * @since 2.0

7566    */

7567   public static String abbreviate(final String str, final int maxWidth) {

7568       final String defaultAbbrevMarker = "...";

7569       return abbreviate(str, defaultAbbrevMarker, 0, maxWidth);

7570   }

7571

7572   /**

7573    * <p>Abbreviates a Stringusing ellipses. This will turn

7574    * "Now is the time for all good men" into "...is the timefor..."</p>

7575    *

7576    * <p>Works like {@code abbreviate(String, int)}, but allows you tospecify

7577    * a "left edge" offset. Note that this left edge is not necessarily going to

7578    * be the leftmost character in the result, or the first characterfollowing the

7579    * ellipses, but it will appear somewhere in the result.

7580    *

7581    * <p>In no case will itreturn a String of length greater than

7582    * {@code maxWidth}.</p>

7583    *

7584    * <pre>

7585    * StringUtils.abbreviate(null, *, *)                = null

7586    * StringUtils.abbreviate("", 0, 4)                  = ""

7587    * StringUtils.abbreviate("abcdefghijklmno", -1, 10) ="abcdefg..."

7588    * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."

7589    * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."

7590    * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."

7591    * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."

7592    * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."

7593    * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"

7594    * StringUtils.abbreviate("abcdefghijklmno", 10, 10) ="...ijklmno"

7595    * StringUtils.abbreviate("abcdefghijklmno", 12, 10) ="...ijklmno"

7596    * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException

7597    * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException

7598    * </pre>

7599    *

7600    * @param str  the String to check,may be null

7601    * @param offset  left edge ofsource String

7602    * @param maxWidth  maximum lengthof result String, must be at least 4

7603    * @return abbreviated String, {@code null} if null String input

7604    * @throws IllegalArgumentException if the width is too small

7605    * @since 2.0

7606    */

7607   public static String abbreviate(final String str, final int offset,final int maxWidth) {

7608       final String defaultAbbrevMarker = "...";

7609       return abbreviate(str, defaultAbbrevMarker, offset, maxWidth);

7610   }

7611

7612   /**

7613    * <p>Abbreviates a String using another given String asreplacement marker. This will turn

7614    * "Now is the time for all good men" into "Now is thetime for..." if "..." was defined

7615    * as the replacement marker.</p>

7616    *

7617    * <p>Specifically:</p>

7618    * <ul>

7619    *   <li>If the number ofcharacters in {@code str} is less than or equal to

7620    *       {@code maxWidth}, return{@code str}.</li>

7621    *   <li>Else abbreviate itto {@code (substring(str, 0, max-abbrevMarker.length) +abbrevMarker)}.</li>

7622    *   <li>If {@code maxWidth}is less than {@code abbrevMarker.length + 1}, throw an

7623    *       {@codeIllegalArgumentException}.</li>

7624    *   <li>In no case will itreturn a String of length greater than

7625    *       {@codemaxWidth}.</li>

7626    * </ul>

7627    *

7628    * <pre>

7629    * StringUtils.abbreviate(null, "...", *)      = null

7630    * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"

7631    * StringUtils.abbreviate("", "...", 4)        = ""

7632    * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."

7633    * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"

7634    * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"

7635    * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."

7636    * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."

7637    * StringUtils.abbreviate("abcdefg", "..", 2)  = IllegalArgumentException

7638    * StringUtils.abbreviate("abcdefg", "...", 3) =IllegalArgumentException

7639    * </pre>

7640    *

7641    * @param str  the String to check,may be null

7642    * @param abbrevMarker  the Stringused as replacement marker

7643    * @param maxWidth  maximum lengthof result String, must be at least {@code abbrevMarker.length + 1}

7644    * @return abbreviated String, {@code null} if null String input

7645    * @throws IllegalArgumentException if the width is too small

7646    * @since 3.6

7647    */

7648   public static String abbreviate(final String str, final StringabbrevMarker, final int maxWidth) {

7649       return abbreviate(str, abbrevMarker, 0, maxWidth);

7650   }

7651

7652   /**

7653    * <p>Abbreviates a String using a given replacement marker. Thiswill turn

7654    * "Now is the time for all good men" into "...is the timefor..." if "..." was defined

7655    * as the replacement marker.</p>

7656    *

7657    * <p>Works like {@code abbreviate(String, String, int)}, butallows you to specify

7658    * a "left edge" offset. Note that this left edge is not necessarily going to

7659    * be the leftmost character in the result, or the first characterfollowing the

7660    * replacement marker, but it will appear somewhere in the result.

7661    *

7662    * <p>In no case will it return a String of length greater than{@code maxWidth}.</p>

7663    *

7664    * <pre>

7665    * StringUtils.abbreviate(null, null, *, *)                 = null

7666    * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"

7667    * StringUtils.abbreviate("", "...", 0, 4)                  = ""

7668    * StringUtils.abbreviate("abcdefghijklmno", "---",-1, 10) = "abcdefg---"

7669    * StringUtils.abbreviate("abcdefghijklmno", ",", 0,10)    = "abcdefghi,"

7670    * StringUtils.abbreviate("abcdefghijklmno", ",", 1,10)    = "abcdefghi,"

7671    * StringUtils.abbreviate("abcdefghijklmno", ",", 2,10)    = "abcdefghi,"

7672    * StringUtils.abbreviate("abcdefghijklmno", "::", 4,10)   = "::efghij::"

7673    * StringUtils.abbreviate("abcdefghijklmno", "...",6, 10)  = "...ghij..."

7674    * StringUtils.abbreviate("abcdefghijklmno", "*", 9,10)    = "*ghijklmno"

7675    * StringUtils.abbreviate("abcdefghijklmno", "'", 10,10)   = "'ghijklmno"

7676    * StringUtils.abbreviate("abcdefghijklmno", "!", 12,10)   = "!ghijklmno"

7677    * StringUtils.abbreviate("abcdefghij", "abra", 0,4)       = IllegalArgumentException

7678    * StringUtils.abbreviate("abcdefghij", "...", 5,6)        = IllegalArgumentException

7679    * </pre>

7680    *

7681    * @param str  the String to check,may be null

7682    * @param abbrevMarker  the Stringused as replacement marker

7683    * @param offset  left edge ofsource String

7684    * @param maxWidth  maximum lengthof result String, must be at least 4

7685    * @return abbreviated String, {@code null} if null String input

7686    * @throws IllegalArgumentException if the width is too small

7687    * @since 3.6

7688    */

7689   public static String abbreviate(final String str, final StringabbrevMarker, int offset, final int maxWidth) {

7690        if (isEmpty(str) ||isEmpty(abbrevMarker)) {

7691            return str;

7692       }

7693

7694       final int abbrevMarkerLength = abbrevMarker.length();

7695       final int minAbbrevWidth = abbrevMarkerLength + 1;

7696       final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength+ 1;

7697

7698       if (maxWidth < minAbbrevWidth) {

7699            throw newIllegalArgumentException(String.format("Minimum abbreviation width is%d", minAbbrevWidth));

7700       }

7701       if (str.length() <= maxWidth) {

7702            return str;

7703       }

7704       if (offset > str.length()) {

7705            offset = str.length();

7706       }

7707       if (str.length() - offset < maxWidth - abbrevMarkerLength) {

7708            offset = str.length() - (maxWidth -abbrevMarkerLength);

7709       }

7710       if (offset <= abbrevMarkerLength+1) {

7711            return str.substring(0, maxWidth -abbrevMarkerLength) + abbrevMarker;

7712       }

7713       if (maxWidth < minAbbrevWidthOffset) {

7714            throw newIllegalArgumentException(String.format("Minimum abbreviation width withoffset is %d", minAbbrevWidthOffset));

7715       }

7716       if (offset + maxWidth - abbrevMarkerLength < str.length()) {

7717            return abbrevMarker +abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);

7718       }

7719       return abbrevMarker + str.substring(str.length() - (maxWidth -abbrevMarkerLength));

7720   }

7721

7722   /**

7723    * <p>Abbreviates a String to the length passed, replacing themiddle characters with the supplied

7724    * replacement String.</p>

7725    *

7726    * <p>This abbreviation only occurs if the following criteria ismet:</p>

7727    * <ul>

7728     * <li>Neither the String forabbreviation nor the replacement String are null or empty </li>

7729    * <li>The length to truncate to is less than the length of thesupplied String</li>

7730    * <li>The length to truncate to is greater than 0</li>

7731    * <li>The abbreviated String will have enough room for the lengthsupplied replacement String

7732    * and the first and last characters of the supplied String forabbreviation</li>

7733    * </ul>

7734    * <p>Otherwise, the returned String will be the same as thesupplied String for abbreviation.

7735    * </p>

7736    *

7737    * <pre>

7738    * StringUtils.abbreviateMiddle(null, null, 0)      = null

7739    * StringUtils.abbreviateMiddle("abc", null, 0)      = "abc"

7740    * StringUtils.abbreviateMiddle("abc", ".", 0)      = "abc"

7741    * StringUtils.abbreviateMiddle("abc", ".", 3)      = "abc"

7742    * StringUtils.abbreviateMiddle("abcdef", ".",4)     = "ab.f"

7743    * </pre>

7744    *

7745    * @param str  the String toabbreviate, may be null

7746    * @param middle the String to replace the middle characters with, may benull

7747    * @param length the length to abbreviate {@code str} to.

7748    * @return the abbreviated String if the above criteria is met, or theoriginal String supplied for abbreviation.

7749    * @since 2.5

7750    */

7751   public static String abbreviateMiddle(final String str, final Stringmiddle, final int length) {

7752       if (isEmpty(str) || isEmpty(middle)) {

7753            return str;

7754       }

7755

7756       if (length >= str.length() || length < middle.length()+2) {

7757            return str;

7758       }

7759

7760       final int targetSting = length-middle.length();

7761       final int startOffset = targetSting/2+targetSting%2;

7762       final int endOffset = str.length()-targetSting/2;

7763

7764       final StringBuilder builder = new StringBuilder(length);

7765       builder.append(str.substring(0,startOffset));

7766       builder.append(middle);

7767       builder.append(str.substring(endOffset));

7768

7769       return builder.toString();

7770   }

7771

7772   // Difference

7773   //-----------------------------------------------------------------------

7774   /**

7775    * <p>Compares two Strings, and returns the portion where theydiffer.

7776    * More precisely, return the remainder of the second String,

7777    * starting from where it's different from the first. This means that

7778    * the difference between "abc" and "ab" is the emptyString and not "c". </p>

7779    *

7780    * <p>For example,

7781    * {@code difference("i am a machine", "i am arobot") -> "robot"}.</p>

7782    *

7783    * <pre>

7784    * StringUtils.difference(null, null) = null

7785    * StringUtils.difference("", "") = ""

7786    * StringUtils.difference("", "abc") ="abc"

7787    * StringUtils.difference("abc", "") = ""

7788    * StringUtils.difference("abc", "abc") =""

7789    * StringUtils.difference("abc", "ab") = ""

7790    * StringUtils.difference("ab", "abxyz") ="xyz"

7791    * StringUtils.difference("abcde", "abxyz") ="xyz"

7792    * StringUtils.difference("abcde", "xyz") ="xyz"

7793    * </pre>

7794    *

7795    * @param str1  the first String,may be null

7796    * @param str2  the second String,may be null

7797    * @return the portion of str2 where it differs from str1; returns the

7798    * empty String if they are equal

7799    * @see #indexOfDifference(CharSequence,CharSequence)

7800    * @since 2.0

7801    */

7802   public static String difference(final String str1, final String str2) {

7803       if (str1 == null) {

7804           return str2;

7805       }

7806       if (str2 == null) {

7807            return str1;

7808       }

7809       final int at = indexOfDifference(str1, str2);

7810       if (at == INDEX_NOT_FOUND) {

7811            return EMPTY;

7812       }

7813        return str2.substring(at);

7814   }

7815

7816   /**

7817    * <p>Compares two CharSequences, and returns the index at whichthe

7818    * CharSequences begin to differ.</p>

7819    *

7820    * <p>For example,

7821    * {@code indexOfDifference("i am a machine", "i am arobot") -> 7}</p>

7822    *

7823    * <pre>

7824    * StringUtils.indexOfDifference(null, null) = -1

7825    * StringUtils.indexOfDifference("", "") = -1

7826    * StringUtils.indexOfDifference("", "abc") = 0

7827    * StringUtils.indexOfDifference("abc", "") = 0

7828    * StringUtils.indexOfDifference("abc", "abc") = -1

7829    * StringUtils.indexOfDifference("ab", "abxyz") = 2

7830    * StringUtils.indexOfDifference("abcde", "abxyz") =2

7831    * StringUtils.indexOfDifference("abcde", "xyz") = 0

7832    * </pre>

7833    *

7834    * @param cs1  the firstCharSequence, may be null

7835    * @param cs2  the secondCharSequence, may be null

7836    * @return the index where cs1 and cs2 begin to differ; -1 if they areequal

7837    * @since 2.0

7838    * @since 3.0 Changed signature from indexOfDifference(String, String) to

7839    * indexOfDifference(CharSequence, CharSequence)

7840    */

7841   public static int indexOfDifference(final CharSequence cs1, finalCharSequence cs2) {

7842       if (cs1 == cs2) {

7843            return INDEX_NOT_FOUND;

7844       }

7845       if (cs1 == null || cs2 == null) {

7846            return 0;

7847       }

7848       int i;

7849       for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {

7850            if (cs1.charAt(i) != cs2.charAt(i)){

7851                break;

7852            }

7853       }

7854       if (i < cs2.length() || i < cs1.length()) {

7855            return i;

7856       }

7857       return INDEX_NOT_FOUND;

7858   }

7859

7860   /**

7861    * <p>Compares all CharSequences in an array and returns the indexat which the

7862    * CharSequences begin to differ.</p>

7863    *

7864    * <p>For example,

7865    * <code>indexOfDifference(new String[] {"i am amachine", "i am a robot"}) -&gt; 7</code></p>

7866    *

7867    * <pre>

7868    * StringUtils.indexOfDifference(null) = -1

7869    * StringUtils.indexOfDifference(new String[] {}) = -1

7870    * StringUtils.indexOfDifference(new String[] {"abc"}) = -1

7871    * StringUtils.indexOfDifference(new String[] {null, null}) = -1

7872    * StringUtils.indexOfDifference(new String[] {"",""}) = -1

7873    * StringUtils.indexOfDifference(new String[] {"", null}) = 0

7874    * StringUtils.indexOfDifference(new String[] {"abc", null,null}) = 0

7875    * StringUtils.indexOfDifference(new String[] {null, null,"abc"}) = 0

7876    * StringUtils.indexOfDifference(new String[] {"","abc"}) = 0

7877    * StringUtils.indexOfDifference(new String[] {"abc",""}) = 0

7878    * StringUtils.indexOfDifference(new String[] {"abc","abc"}) = -1

7879    * StringUtils.indexOfDifference(new String[] {"abc","a"}) = 1

7880    * StringUtils.indexOfDifference(new String[] {"ab","abxyz"}) = 2

7881    * StringUtils.indexOfDifference(new String[] {"abcde","abxyz"}) = 2

7882    * StringUtils.indexOfDifference(new String[] {"abcde","xyz"}) = 0

7883    * StringUtils.indexOfDifference(new String[] {"xyz","abcde"}) = 0

7884    * StringUtils.indexOfDifference(new String[] {"i am amachine", "i am a robot"}) = 7

7885    * </pre>

7886    *

7887    * @param css  array ofCharSequences, entries may be null

7888    * @return the index where the strings begin to differ; -1 if they areall equal

7889    * @since 2.4

7890    * @since 3.0 Changed signature from indexOfDifference(String...) toindexOfDifference(CharSequence...)

7891    */

7892   public static int indexOfDifference(final CharSequence... css) {

7893       if (css == null || css.length <= 1) {

7894           return INDEX_NOT_FOUND;

7895       }

7896       boolean anyStringNull = false;

7897       boolean allStringsNull = true;

7898       final int arrayLen = css.length;

7899       int shortestStrLen = Integer.MAX_VALUE;

7900       int longestStrLen = 0;

7901

7902       // find the min and max string lengths; this avoids checking to make

7903       // sure we are not exceeding the length of the string each time through

7904       // the bottom loop.

7905       for (CharSequence cs : css) {

7906           if (cs == null) {

7907                anyStringNull = true;

7908                shortestStrLen = 0;

7909            } else {

7910                allStringsNull = false;

7911                shortestStrLen =Math.min(cs.length(), shortestStrLen);

7912                longestStrLen =Math.max(cs.length(), longestStrLen);

7913            }

7914       }

7915

7916       // handle lists containing all nulls or all empty strings

7917       if (allStringsNull || longestStrLen == 0 && !anyStringNull) {

7918            return INDEX_NOT_FOUND;

7919       }

7920

7921       // handle lists containing some nulls or some empty strings

7922       if (shortestStrLen == 0) {

7923            return 0;

7924       }

7925

7926       // find the position with the first difference across all strings

7927       int firstDiff = -1;

7928       for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {

7929            final char comparisonChar =css[0].charAt(stringPos);

7930            for (int arrayPos = 1; arrayPos< arrayLen; arrayPos++) {

7931                if(css[arrayPos].charAt(stringPos) != comparisonChar) {

7932                    firstDiff = stringPos;

7933                    break;

7934                }

7935            }

7936            if (firstDiff != -1) {

7937                break;

7938            }

7939       }

7940

7941       if (firstDiff == -1 && shortestStrLen != longestStrLen) {

7942            // we compared all of thecharacters up to the length of the

7943            // shortest string and didn't finda match, but the string lengths

7944            // vary, so return the length ofthe shortest string.

7945            return shortestStrLen;

7946       }

7947       return firstDiff;

7948   }

7949

7950   /**

7951    * <p>Compares all Strings in an array and returns the initialsequence of

7952    * characters that is common to all of them.</p>

7953    *

7954    * <p>For example,

7955    * <code>getCommonPrefix(new String[] {"i am a machine","i am a robot"}) -&gt; "i am a "</code></p>

7956    *

7957    * <pre>

7958    * StringUtils.getCommonPrefix(null) = ""

7959    * StringUtils.getCommonPrefix(new String[] {}) = ""

7960    * StringUtils.getCommonPrefix(new String[] {"abc"}) ="abc"

7961    * StringUtils.getCommonPrefix(new String[] {null, null}) = ""

7962    * StringUtils.getCommonPrefix(new String[] {"", ""})= ""

7963    * StringUtils.getCommonPrefix(new String[] {"", null}) =""

7964    * StringUtils.getCommonPrefix(new String[] {"abc", null,null}) = ""

7965    * StringUtils.getCommonPrefix(new String[] {null, null,"abc"}) = ""

7966    * StringUtils.getCommonPrefix(new String[] {"","abc"}) = ""

7967    * StringUtils.getCommonPrefix(new String[] {"abc",""}) = ""

7968    * StringUtils.getCommonPrefix(new String[] {"abc","abc"}) = "abc"

7969    * StringUtils.getCommonPrefix(new String[] {"abc","a"}) = "a"

7970    * StringUtils.getCommonPrefix(new String[] {"ab","abxyz"}) = "ab"

7971    * StringUtils.getCommonPrefix(new String[] {"abcde","abxyz"}) = "ab"

7972    * StringUtils.getCommonPrefix(new String[] {"abcde","xyz"}) = ""

7973    * StringUtils.getCommonPrefix(new String[] {"xyz","abcde"}) = ""

7974    * StringUtils.getCommonPrefix(new String[] {"i am a machine","i am a robot"}) = "i am a "

7975    * </pre>

7976    *

7977    * @param strs  array of Stringobjects, entries may be null

7978    * @return the initial sequence of characters that are common to all Strings

7979    * in the array; empty String if the array is null, the elements are allnull

7980    * or if there is no common prefix.

7981    * @since 2.4

7982    */

7983   public static String getCommonPrefix(final String... strs) {

7984       if (strs == null || strs.length == 0) {

7985            return EMPTY;

7986       }

7987       final int smallestIndexOfDiff = indexOfDifference(strs);

7988       if (smallestIndexOfDiff == INDEX_NOT_FOUND) {

7989            // all strings were identical

7990            if (strs[0] == null) {

7991                return EMPTY;

7992            }

7993            return strs[0];

7994       } else if (smallestIndexOfDiff == 0) {

7995            // there were no common initialcharacters

7996            return EMPTY;

7997       } else {

7998            // we found a common initialcharacter sequence

7999            return strs[0].substring(0,smallestIndexOfDiff);

8000       }

8001   }

8002

8003   // Misc

8004   //-----------------------------------------------------------------------

8005   /**

8006    * <p>Find the Levenshtein distance between two Strings.</p>

8007    *

8008    * <p>This is the number of changes needed to change one Stringinto

8009    * another, where each change is a single character modification(deletion,

8010    * insertion or substitution).</p>

8011    *

8012    * <p>The implementation uses a single-dimensional array of lengths.length() + 1. See

8013    * <a href="http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">

8014    *http://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a>for details.</p>

8015    *

8016    * <pre>

8017    * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException

8018    * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException

8019    * StringUtils.getLevenshteinDistance("","")               = 0

8020    * StringUtils.getLevenshteinDistance("","a")              = 1

8021    * StringUtils.getLevenshteinDistance("aaapppp","")       = 7

8022    * StringUtils.getLevenshteinDistance("frog","fog")       = 1

8023    * StringUtils.getLevenshteinDistance("fly","ant")        = 3

8024    * StringUtils.getLevenshteinDistance("elephant","hippo") = 7

8025    * StringUtils.getLevenshteinDistance("hippo","elephant") = 7

8026    * StringUtils.getLevenshteinDistance("hippo","zzzzzzzz") = 8

8027    * StringUtils.getLevenshteinDistance("hello","hallo")    = 1

8028    * </pre>

8029    *

8030    * @param s  the first String, mustnot be null

8031    * @param t  the second String,must not be null

8032    * @return result distance

8033    * @throws IllegalArgumentException if either String input {@code null}

8034    * @since 3.0 Changed signature from getLevenshteinDistance(String,String) to

8035    * getLevenshteinDistance(CharSequence, CharSequence)

8036    * @deprecated as of 3.6, use commons-text

8037    * <ahref="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">

8038    * LevenshteinDistance</a> instead

8039    */

8040   @Deprecated

8041   public static int getLevenshteinDistance(CharSequence s, CharSequence t){

8042       if (s == null || t == null) {

8043            throw newIllegalArgumentException("Strings must not be null");

8044       }

8045

8046       int n = s.length();

8047       int m = t.length();

8048

8049       if (n == 0) {

8050            return m;

8051       } else if (m == 0) {

8052            return n;

8053       }

8054

8055       if (n > m) {

8056            // swap the input strings to consumeless memory

8057            final CharSequence tmp = s;

8058            s = t;

8059            t = tmp;

8060            n = m;

8061            m = t.length();

8062       }

8063

8064       final int p[] = new int[n + 1];

8065       // indexes into strings s and t

8066       int i; // iterates through s

8067       int j; // iterates through t

8068       int upper_left;

8069       int upper;

8070

8071       char t_j; // jth character of t

8072       int cost;

8073

8074       for (i = 0; i <= n; i++) {

8075            p[i] = i;

8076       }

8077

8078       for (j = 1; j <= m; j++) {

8079            upper_left = p[0];

8080            t_j = t.charAt(j - 1);

8081            p[0] = j;

8082

8083            for (i = 1; i <= n; i++) {

8084                upper = p[i];

8085                cost = s.charAt(i - 1) == t_j ?0 : 1;

8086                // minimum of cell to theleft+1, to the top+1, diagonally left and up +cost

8087                p[i] = Math.min(Math.min(p[i -1] + 1, p[i] + 1), upper_left + cost);

8088                upper_left = upper;

8089            }

8090       }

8091

8092       return p[n];

8093   }

8094

8095   /**

8096    * <p>Find the Levenshtein distance between two Strings if it'sless than or equal to a given

8097    * threshold.</p>

8098    *

8099    * <p>This is the number of changes needed to change one Stringinto

8100    * another, where each change is a single character modification(deletion,

8101    * insertion or substitution).</p>

8102    *

8103    * <p>This implementation follows from Algorithms on Strings, Treesand Sequences by Dan Gusfield

8104    * and Chas Emerick's implementation of the Levenshtein distancealgorithm from

8105    * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>

8106    *

8107    * <pre>

8108    * StringUtils.getLevenshteinDistance(null, *, *)             = IllegalArgumentException

8109    * StringUtils.getLevenshteinDistance(*, null, *)             = IllegalArgumentException

8110    * StringUtils.getLevenshteinDistance(*, *, -1)               = IllegalArgumentException

8111    * StringUtils.getLevenshteinDistance("","", 0)               = 0

8112    * StringUtils.getLevenshteinDistance("aaapppp", "",8)       = 7

8113    * StringUtils.getLevenshteinDistance("aaapppp", "",7)       = 7

8114    * StringUtils.getLevenshteinDistance("aaapppp", "",6))      = -1

8115    * StringUtils.getLevenshteinDistance("elephant","hippo", 7) = 7

8116    * StringUtils.getLevenshteinDistance("elephant","hippo", 6) = -1

8117    * StringUtils.getLevenshteinDistance("hippo","elephant", 7) = 7

8118    * StringUtils.getLevenshteinDistance("hippo","elephant", 6) = -1

8119    * </pre>

8120    *

8121    * @param s  the first String, must not be null

8122    * @param t  the second String,must not be null

8123    * @param threshold the target threshold, must not be negative

8124    * @return result distance, or {@code -1} if the distance would be greaterthan the threshold

8125    * @throws IllegalArgumentException if either String input {@code null}or negative threshold

8126    * @deprecated as of 3.6, use commons-text

8127    * <ahref="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">

8128    * LevenshteinDistance</a> instead

8129    */

8130   @Deprecated

8131   public static int getLevenshteinDistance(CharSequence s, CharSequence t,final int threshold) {

8132       if (s == null || t == null) {

8133            throw newIllegalArgumentException("Strings must not be null");

8134       }

8135       if (threshold < 0) {

8136            throw newIllegalArgumentException("Threshold must not be negative");

8137        }

8138

8139       /*

8140       This implementation only computes the distance if it's less than orequal to the

8141       threshold value, returning -1 if it's greater.  The advantage is performance: unbounded

8142       distance is O(nm), but a bound of k allows us to reduce it to O(km) timeby only

8143       computing a diagonal stripe of width 2k + 1 of the cost table.

8144       It is also possible to use this to compute the unbounded Levenshteindistance by starting

8145       the threshold at 1 and doubling each time until the distance is found;this is O(dm), where

8146       d is the distance.

8147

8148       One subtlety comes from needing to ignore entries on the border of ourstripe

8149       eg.

8150       p[] = |#|#|#|*

8151       d[] =  *|#|#|#|

8152       We must ignore the entry to the left of the leftmost member

8153       We must ignore the entry above the rightmost member

8154

8155       Another subtlety comes from our stripe running off the matrix if thestrings aren't

8156       of the same size.  Since string sis always swapped to be the shorter of the two,

8157       the stripe will always run off to the upper right instead of the lowerleft of the matrix.

8158

8159       As a concrete example, suppose s is of length 5, t is of length 7, andour threshold is 1.

8160       In this case we're going to walk a stripe of length 3.  The matrix would look like so:

8161

8162           1 2 3 4 5

8163       1 |#|#| | | |

8164       2 |#|#|#| | |

8165       3 | |#|#|#| |

8166       4 | | |#|#|#|

8167       5 | | | |#|#|

8168       6 | | | | |#|

8169       7 | | | | | |

8170

8171       Note how the stripe leads off the table as there is no possible way toturn a string of length 5

8172       into one of length 7 in edit distance of 1.

8173

8174       Additionally, this implementation decreases memory usage by using two

8175       single-dimensional arrays and swapping them back and forth instead ofallocating

8176       an entire n by m matrix.  Thisrequires a few minor changes, such as immediately returning

8177       when it's detected that the stripe has run off the matrix and initiallyfilling the arrays with

8178       large values so that entries we don't compute are ignored.

8179

8180       See Algorithms on Strings, Trees and Sequences by Dan Gusfield for somediscussion.

8181        */

8182

8183       int n = s.length(); // length of s

8184       int m = t.length(); // length of t

8185

8186       // if one string is empty, the edit distance is necessarily the lengthof the other

8187       if (n == 0) {

8188            return m <= threshold ? m : -1;

8189       } else if (m == 0) {

8190            return n <= threshold ? n : -1;

8191       } else if (Math.abs(n - m) > threshold) {

8192            // no need to calculate thedistance if the length difference is greater than the threshold

8193            return -1;

8194       }

8195

8196       if (n > m) {

8197            // swap the two strings to consumeless memory

8198            final CharSequence tmp = s;

8199            s = t;

8200            t = tmp;

8201            n = m;

8202            m = t.length();

8203       }

8204

8205       int p[] = new int[n + 1]; // 'previous' cost array, horizontally

8206       int d[] = new int[n + 1]; // cost array, horizontally

8207       int _d[]; // placeholder to assist in swapping p and d

8208

8209       // fill in starting table values

8210       final int boundary = Math.min(n, threshold) + 1;

8211       for (int i = 0; i < boundary; i++) {

8212            p[i] = i;

8213       }

8214       // these fills ensure that the value above the rightmost entry of our

8215       // stripe will be ignored in following loop iterations

8216       Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);

8217       Arrays.fill(d, Integer.MAX_VALUE);

8218

8219       // iterates through t

8220       for (int j = 1; j <= m; j++) {

8221            final char t_j = t.charAt(j - 1);// jth character of t

8222            d[0] = j;

8223

8224            // compute stripe indices,constrain to array size

8225            final int min = Math.max(1, j -threshold);

8226            final int max = j >Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);

8227

8228            // the stripe may lead off of thetable if s and t are of different sizes

8229            if (min > max) {

8230                return -1;

8231            }

8232

8233            // ignore entry left of leftmost

8234            if (min > 1) {

8235                d[min - 1] = Integer.MAX_VALUE;

8236            }

8237

8238            // iterates through [min, max] in s

8239            for (int i = min; i <= max; i++){

8240                if (s.charAt(i - 1) == t_j) {

8241                    // diagonally left and up

8242                    d[i] = p[i - 1];

8243                } else {

8244                    // 1 + minimum of cell tothe left, to the top, diagonally left and up

8245                    d[i] = 1 + Math.min(Math.min(d[i- 1], p[i]), p[i - 1]);

8246                }

8247            }

8248

8249            // copy current distance counts to'previous row' distance counts

8250            _d = p;

8251            p = d;

8252            d = _d;

8253       }

8254

8255       // if p[n] is greater than the threshold, there's no guarantee on itbeing the correct

8256       // distance

8257       if (p[n] <= threshold) {

8258            return p[n];

8259       }

8260       return -1;

8261   }

8262

8263   /**

8264    * <p>Find the Jaro Winkler Distance which indicates the similarityscore between two Strings.</p>

8265    *

8266    * <p>The Jaro measure is the weighted sum of percentage of matchedcharacters from each file and transposed characters.

8267    * Winkler increased this measure for matching initialcharacters.</p>

8268    *

8269    * <p>This implementation is based on the Jaro Winkler similarityalgorithm

8270    * from <ahref="http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p>

8271    *

8272    * <pre>

8273    * StringUtils.getJaroWinklerDistance(null, null)          = IllegalArgumentException

8274    * StringUtils.getJaroWinklerDistance("","")               = 0.0

8275    * StringUtils.getJaroWinklerDistance("","a")              = 0.0

8276    * StringUtils.getJaroWinklerDistance("aaapppp","")       = 0.0

8277    * StringUtils.getJaroWinklerDistance("frog","fog")       = 0.93

8278    * StringUtils.getJaroWinklerDistance("fly","ant")        = 0.0

8279    * StringUtils.getJaroWinklerDistance("elephant","hippo") = 0.44

8280    * StringUtils.getJaroWinklerDistance("hippo","elephant") = 0.44

8281    * StringUtils.getJaroWinklerDistance("hippo","zzzzzzzz") = 0.0

8282    * StringUtils.getJaroWinklerDistance("hello","hallo")    = 0.88

8283    * StringUtils.getJaroWinklerDistance("ABC Corporation","ABC Corp") = 0.93

8284    * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc","D &amp; H Enterprises, Inc.") = 0.95

8285    * StringUtils.getJaroWinklerDistance("My Gym Children's FitnessCenter", "My Gym. Childrens Fitness") = 0.92

8286    * StringUtils.getJaroWinklerDistance("PENNSYLVANIA","PENNCISYLVNIA") = 0.88

8287    * </pre>

8288    *

8289    * @param first the first String, must not be null

8290    * @param second the second String, must not be null

8291    * @return result distance

8292    * @throws IllegalArgumentException if either String input {@code null}

8293    * @since 3.3

8294    * @deprecated as of 3.6, use commons-text

8295    * <ahref="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">

8296    * JaroWinklerDistance</a> instead

8297    */

8298   @Deprecated

8299   public static double getJaroWinklerDistance(final CharSequence first,final CharSequence second) {

8300       final double DEFAULT_SCALING_FACTOR = 0.1;

8301

8302       if (first == null || second == null) {

8303            throw newIllegalArgumentException("Strings must not be null");

8304       }

8305

8306       final int[] mtp = matches(first, second);

8307       final double m = mtp[0];

8308       if (m == 0) {

8309            return 0D;

8310       }

8311       final double j = ((m / first.length() + m / second.length() + (m -mtp[1]) / m)) / 3;

8312       final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR,1D / mtp[3]) * mtp[2] * (1D - j);

8313       return Math.round(jw * 100.0D) / 100.0D;

8314   }

8315

8316   private static int[] matches(final CharSequence first, finalCharSequence second) {

8317       CharSequence max, min;

8318       if (first.length() > second.length()) {

8319            max = first;

8320            min = second;

8321       } else {

8322            max = second;

8323            min = first;

8324       }

8325       final int range = Math.max(max.length() / 2 - 1, 0);

8326       final int[] matchIndexes = new int[min.length()];

8327       Arrays.fill(matchIndexes, -1);

8328       final boolean[] matchFlags = new boolean[max.length()];

8329       int matches = 0;

8330       for (int mi = 0; mi < min.length(); mi++) {

8331            final char c1 = min.charAt(mi);

8332            for (int xi = Math.max(mi - range,0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {

8333                if (!matchFlags[xi] &&c1 == max.charAt(xi)) {

8334                    matchIndexes[mi] = xi;

8335                    matchFlags[xi] = true;

8336                    matches++;

8337                    break;

8338                }

8339            }

8340       }

8341       final char[] ms1 = new char[matches];

8342       final char[] ms2 = new char[matches];

8343       for (int i = 0, si = 0; i < min.length(); i++) {

8344            if (matchIndexes[i] != -1) {

8345                ms1[si] = min.charAt(i);

8346                si++;

8347            }

8348       }

8349       for (int i = 0, si = 0; i < max.length(); i++) {

8350            if (matchFlags[i]) {

8351                ms2[si] = max.charAt(i);

8352                si++;

8353            }

8354       }

8355       int transpositions = 0;

8356       for (int mi = 0; mi < ms1.length; mi++) {

8357            if (ms1[mi] != ms2[mi]) {

8358                transpositions++;

8359            }

8360       }

8361       int prefix = 0;

8362       for (int mi = 0; mi < min.length(); mi++) {

8363            if (first.charAt(mi) ==second.charAt(mi)) {

8364                prefix++;

8365            } else {

8366                break;

8367            }

8368       }

8369       return new int[] { matches, transpositions / 2, prefix, max.length() };

8370   }

8371

8372   /**

8373    * <p>Find the Fuzzy Distance which indicates the similarity scorebetween two Strings.</p>

8374    *

8375    * <p>This string matching algorithm is similar to the algorithmsof editors such as Sublime Text,

8376    * TextMate, Atom and others. One point is given for every matchedcharacter. Subsequent

8377    * matches yield two bonus points. A higher score indicates a highersimilarity.</p>

8378    *

8379    * <pre>

8380    * StringUtils.getFuzzyDistance(null, null, null)                                    =IllegalArgumentException

8381    * StringUtils.getFuzzyDistance("", "",Locale.ENGLISH)                             = 0

8382    * StringUtils.getFuzzyDistance("Workshop", "b",Locale.ENGLISH)                     = 0

8383    * StringUtils.getFuzzyDistance("Room", "o",Locale.ENGLISH)                         =1

8384    * StringUtils.getFuzzyDistance("Workshop", "w",Locale.ENGLISH)                     = 1

8385    * StringUtils.getFuzzyDistance("Workshop", "ws",Locale.ENGLISH)                    = 2

8386    * StringUtils.getFuzzyDistance("Workshop", "wo",Locale.ENGLISH)                    = 4

8387    * StringUtils.getFuzzyDistance("Apache Software Foundation","asf", Locale.ENGLISH) = 3

8388    * </pre>

8389    *

8390    * @param term a full term that should be matched against, must not benull

8391    * @param query the query that will be matched against a term, must notbe null

8392    * @param locale This string matching logic is case insensitive. A localeis necessary to normalize

8393    *  both Strings to lower case.

8394    * @return result score

8395    * @throws IllegalArgumentException if either String input {@code null}or Locale input {@code null}

8396    * @since 3.4

8397    * @deprecated as of 3.6, use commons-text

8398    * <ahref="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">

8399    * FuzzyScore</a> instead

8400    */

8401   @Deprecated

8402   public static int getFuzzyDistance(final CharSequence term, finalCharSequence query, final Locale locale) {

8403       if (term == null || query == null) {

8404            throw newIllegalArgumentException("Strings must not be null");

8405       } else if (locale == null) {

8406            throw newIllegalArgumentException("Locale must not be null");

8407       }

8408

8409       // fuzzy logic is case insensitive. We normalize the Strings to lower

8410       // case right from the start. Turning characters to lower case

8411       // via Character.toLowerCase(char) is unfortunately insufficient

8412       // as it does not accept a locale.

8413       final String termLowerCase = term.toString().toLowerCase(locale);

8414       final String queryLowerCase = query.toString().toLowerCase(locale);

8415

8416       // the resulting score

8417       int score = 0;

8418

8419       // the position in the term which will be scanned next for potential

8420       // query character matches

8421       int termIndex = 0;

8422

8423       // index of the previously matched character in the term

8424       int previousMatchingCharacterIndex = Integer.MIN_VALUE;

8425

8426       for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++){

8427            final char queryChar =queryLowerCase.charAt(queryIndex);

8428

8429            boolean termCharacterMatchFound =false;

8430            for (; termIndex <termLowerCase.length() && !termCharacterMatchFound; termIndex++) {

8431                final char termChar =termLowerCase.charAt(termIndex);

8432

8433                if (queryChar == termChar) {

8434                    // simple character matchesresult in one point

8435                    score++;

8436

8437                    // subsequent character matches furtherimprove

8438                    // the score.

8439                    if(previousMatchingCharacterIndex + 1 == termIndex) {

8440                        score += 2;

8441                    }

8442

8443                   previousMatchingCharacterIndex = termIndex;

8444

8445                    // we can leave the nestedloop. Every character in the

8446                    // query can match at mostone character in the term.

8447                    termCharacterMatchFound =true;

8448                }

8449            }

8450       }

8451

8452       return score;

8453   }

8454

8455   // startsWith

8456   //-----------------------------------------------------------------------

8457

8458   /**

8459    * <p>Check if a CharSequence starts with a specifiedprefix.</p>

8460    *

8461    * <p>{@code null}s are handled without exceptions. Two {@codenull}

8462    * references are considered to be equal. The comparison is case sensitive.</p>

8463    *

8464    * <pre>

8465    * StringUtils.startsWith(null, null)     = true

8466    * StringUtils.startsWith(null, "abc")     = false

8467    * StringUtils.startsWith("abcdef", null)  = false

8468    * StringUtils.startsWith("abcdef", "abc") = true

8469    * StringUtils.startsWith("ABCDEF", "abc") = false

8470    * </pre>

8471    *

8472    * @see java.lang.String#startsWith(String)

8473    * @param str  the CharSequence tocheck, may be null

8474    * @param prefix the prefix to find, may be null

8475    * @return {@code true} if the CharSequence starts with the prefix, casesensitive, or

8476    *  both {@code null}

8477    * @since 2.4

8478    * @since 3.0 Changed signature from startsWith(String, String) tostartsWith(CharSequence, CharSequence)

8479    */

8480   public static boolean startsWith(final CharSequence str, finalCharSequence prefix) {

8481       return startsWith(str, prefix, false);

8482   }

8483

8484   /**

8485    * <p>Case insensitive check if a CharSequence starts with aspecified prefix.</p>

8486    *

8487    * <p>{@code null}s are handled without exceptions. Two {@codenull}

8488    * references are considered to be equal. The comparison is case insensitive.</p>

8489    *

8490    * <pre>

8491    * StringUtils.startsWithIgnoreCase(null, null)      = true

8492    * StringUtils.startsWithIgnoreCase(null, "abc")     = false

8493    * StringUtils.startsWithIgnoreCase("abcdef", null)  = false

8494    * StringUtils.startsWithIgnoreCase("abcdef", "abc")= true

8495    * StringUtils.startsWithIgnoreCase("ABCDEF", "abc")= true

8496    * </pre>

8497    *

8498    * @see java.lang.String#startsWith(String)

8499    * @param str  the CharSequence to check,may be null

8500    * @param prefix the prefix to find, may be null

8501    * @return {@code true} if the CharSequence starts with the prefix, caseinsensitive, or

8502    *  both {@code null}

8503    * @since 2.4

8504    * @since 3.0 Changed signature from startsWithIgnoreCase(String, String)to startsWithIgnoreCase(CharSequence, CharSequence)

8505    */

8506   public static boolean startsWithIgnoreCase(final CharSequence str, finalCharSequence prefix) {

8507       return startsWith(str, prefix, true);

8508   }

8509

8510   /**

8511    * <p>Check if a CharSequence starts with a specified prefix(optionally case insensitive).</p>

8512    *

8513    * @see java.lang.String#startsWith(String)

8514    * @param str  the CharSequence tocheck, may be null

8515    * @param prefix the prefix to find, may be null

8516    * @param ignoreCase indicates whether the compare should ignore case

8517    *  (case insensitive) or not.

8518    * @return {@code true} if the CharSequence starts with the prefix or

8519    *  both {@code null}

8520    */

8521   private static boolean startsWith(final CharSequence str, finalCharSequence prefix, final boolean ignoreCase) {

8522       if (str == null || prefix == null) {

8523            return str == null &&prefix == null;

8524       }

8525       if (prefix.length() > str.length()) {

8526            return false;

8527       }

8528       return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0,prefix.length());

8529   }

8530

8531   /**

8532    * <p>Check if a CharSequence starts with any of the providedcase-sensitive prefixes.</p>

8533    *

8534    * <pre>

8535     * StringUtils.startsWithAny(null, null)      = false

8536    * StringUtils.startsWithAny(null, new String[] {"abc"})  = false

8537    * StringUtils.startsWithAny("abcxyz", null)     = false

8538    * StringUtils.startsWithAny("abcxyz", new String[]{""}) = true

8539    * StringUtils.startsWithAny("abcxyz", new String[]{"abc"}) = true

8540    * StringUtils.startsWithAny("abcxyz", new String[] {null,"xyz", "abc"}) = true

8541    * StringUtils.startsWithAny("abcxyz", null, "xyz","ABCX") = false

8542    * StringUtils.startsWithAny("ABCXYZ", null, "xyz","abc") = false

8543    * </pre>

8544    *

8545    * @param sequence the CharSequence to check, may be null

8546    * @param searchStrings the case-sensitive CharSequence prefixes, may beempty or contain {@code null}

8547    * @see StringUtils#startsWith(CharSequence, CharSequence)

8548    * @return {@code true} if the input {@code sequence} is {@code null} ANDno {@code searchStrings} are provided, or

8549    *   the input {@code sequence}begins with any of the provided case-sensitive {@code searchStrings}.

8550    * @since 2.5

8551    * @since 3.0 Changed signature from startsWithAny(String, String[]) tostartsWithAny(CharSequence, CharSequence...)

8552    */

8553   public static boolean startsWithAny(final CharSequence sequence, finalCharSequence... searchStrings) {

8554       if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {

8555            return false;

8556       }

8557       for (final CharSequence searchString : searchStrings) {

8558            if (startsWith(sequence,searchString)) {

8559                return true;

8560            }

8561       }

8562       return false;

8563   }

8564

8565   // endsWith

8566   //-----------------------------------------------------------------------

8567

8568   /**

8569    * <p>Check if a CharSequence ends with a specifiedsuffix.</p>

8570    *

8571    * <p>{@code null}s are handled without exceptions. Two {@codenull}

8572    * references are considered to be equal. The comparison is casesensitive.</p>

8573    *

8574    * <pre>

8575    * StringUtils.endsWith(null, null)     = true

8576    * StringUtils.endsWith(null, "def")     = false

8577    * StringUtils.endsWith("abcdef", null)  = false

8578    * StringUtils.endsWith("abcdef", "def") = true

8579    * StringUtils.endsWith("ABCDEF", "def") = false

8580    * StringUtils.endsWith("ABCDEF", "cde") = false

8581    * StringUtils.endsWith("ABCDEF", "")    = true

8582    * </pre>

8583    *

8584    * @see java.lang.String#endsWith(String)

8585    * @param str  the CharSequence tocheck, may be null

8586    * @param suffix the suffix to find, may be null

8587    * @return {@code true} if the CharSequence ends with the suffix, casesensitive, or

8588    *  both {@code null}

8589    * @since 2.4

8590    * @since 3.0 Changed signature from endsWith(String, String) toendsWith(CharSequence, CharSequence)

8591    */

8592   public static boolean endsWith(final CharSequence str, finalCharSequence suffix) {

8593       return endsWith(str, suffix, false);

8594   }

8595

8596   /**

8597    * <p>Case insensitive check if a CharSequence ends with aspecified suffix.</p>

8598    *

8599    * <p>{@code null}s are handled without exceptions. Two {@codenull}

8600    * references are considered to be equal. The comparison is caseinsensitive.</p>

8601    *

8602    * <pre>

8603    * StringUtils.endsWithIgnoreCase(null, null)      = true

8604    * StringUtils.endsWithIgnoreCase(null, "def")     = false

8605    * StringUtils.endsWithIgnoreCase("abcdef", null)  = false

8606    * StringUtils.endsWithIgnoreCase("abcdef", "def") =true

8607    * StringUtils.endsWithIgnoreCase("ABCDEF", "def") =true

8608    * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") =false

8609    * </pre>

8610    *

8611    * @see java.lang.String#endsWith(String)

8612    * @param str  the CharSequence tocheck, may be null

8613    * @param suffix the suffix to find, may be null

8614    * @return {@code true} if the CharSequence ends with the suffix, caseinsensitive, or

8615    *  both {@code null}

8616    * @since 2.4

8617    * @since 3.0 Changed signature from endsWithIgnoreCase(String, String)to endsWithIgnoreCase(CharSequence, CharSequence)

8618    */

8619   public static boolean endsWithIgnoreCase(final CharSequence str, finalCharSequence suffix) {

8620        return endsWith(str, suffix, true);

8621   }

8622

8623   /**

8624    * <p>Check if a CharSequence ends with a specified suffix(optionally case insensitive).</p>

8625    *

8626    * @see java.lang.String#endsWith(String)

8627    * @param str  the CharSequence tocheck, may be null

8628    * @param suffix the suffix to find, may be null

8629    * @param ignoreCase indicates whether the compare should ignore case

8630    *  (case insensitive) or not.

8631    * @return {@code true} if the CharSequence starts with the prefix or

8632    *  both {@code null}

8633    */

8634   private static boolean endsWith(final CharSequence str, finalCharSequence suffix, final boolean ignoreCase) {

8635       if (str == null || suffix == null) {

8636            return str == null &&suffix == null;

8637       }

8638       if (suffix.length() > str.length()) {

8639            return false;

8640       }

8641       final int strOffset = str.length() - suffix.length();

8642       return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset,suffix, 0, suffix.length());

8643   }

8644

8645   /**

8646    * <p>

8647    * Similar to <a

8648    *href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize

8649    * -space</a>

8650    * </p>

8651    * <p>

8652    * The function returns the argument string with whitespace normalized byusing

8653    * <code>{@link #trim(String)}</code> to remove leading andtrailing whitespace

8654    * and then replacing sequences of whitespace characters by a singlespace.

8655    * </p>

8656    * In XML Whitespace characters are the same as those allowed by the<a

8657    * href="http://www.w3.org/TR/REC-xml/#NT-S">S</a>production, which is S ::= (#x20 | #x9 | #xD | #xA)+

8658    * <p>

8659    * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]

8660    *

8661    * <p>For reference:</p>

8662    * <ul>

8663    * <li>\x0B = vertical tab</li>

8664    * <li>\f = #xC = form feed</li>

8665    * <li>#x20 = space</li>

8666    * <li>#x9 = \t</li>

8667    * <li>#xA = \n</li>

8668    * <li>#xD = \r</li>

8669    * </ul>

8670    *

8671    * <p>

8672    * The difference is that Java's whitespace includes vertical tab andform feed, which this functional will also

8673    * normalize. Additionally <code>{@link #trim(String)}</code>removes control characters (char &lt;= 32) from both

8674    * ends of this String.

8675    * </p>

8676    *

8677    * @see Pattern

8678    * @see #trim(String)

8679    * @see <a

8680    *     href="http://www.w3.org/TR/xpath/#function-normalize-space">http://www.w3.org/TR/xpath/#function-normalize-space</a>

8681    * @param str the source String to normalize whitespaces from, may benull

8682    * @return the modified string with whitespace normalized, {@code null}if null String input

8683    *

8684    * @since 3.0

8685    */

8686   public static String normalizeSpace(final String str) {

8687       // LANG-1020: Improved performance significantly by normalizing manuallyinstead of using regex

8688       // Seehttps://github.com/librucha/commons-lang-normalizespaces-benchmark forperformance test

8689       if (isEmpty(str)) {

8690            return str;

8691       }

8692       final int size = str.length();

8693       final char[] newChars = new char[size];

8694       int count = 0;

8695       int whitespacesCount = 0;

8696       boolean startWhitespaces = true;

8697       for (int i = 0; i < size; i++) {

8698            final char actualChar =str.charAt(i);

8699            final boolean isWhitespace =Character.isWhitespace(actualChar);

8700            if (!isWhitespace) {

8701                startWhitespaces = false;

8702                newChars[count++] = (actualChar== 160 ? 32 : actualChar);

8703                whitespacesCount = 0;

8704            } else {

8705                if (whitespacesCount == 0&& !startWhitespaces) {

8706                    newChars[count++] =SPACE.charAt(0);

8707                }

8708                whitespacesCount++;

8709            }

8710       }

8711       if (startWhitespaces) {

8712            return EMPTY;

8713       }

8714       return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 :0)).trim();

8715   }

8716

8717   /**

8718    * <p>Check if a CharSequence ends with any of the providedcase-sensitive suffixes.</p>

8719    *

8720    * <pre>

8721    * StringUtils.endsWithAny(null, null)      = false

8722    * StringUtils.endsWithAny(null, new String[] {"abc"})  = false

8723    * StringUtils.endsWithAny("abcxyz", null)     = false

8724    * StringUtils.endsWithAny("abcxyz", new String[]{""}) = true

8725    * StringUtils.endsWithAny("abcxyz", new String[]{"xyz"}) = true

8726    * StringUtils.endsWithAny("abcxyz", new String[] {null,"xyz", "abc"}) = true

8727    * StringUtils.endsWithAny("abcXYZ", "def","XYZ") = true

8728    * StringUtils.endsWithAny("abcXYZ", "def","xyz") = false

8729    * </pre>

8730    *

8731    * @param sequence  theCharSequence to check, may be null

8732    * @param searchStrings the case-sensitive CharSequences to find, may beempty or contain {@code null}

8733    * @see StringUtils#endsWith(CharSequence, CharSequence)

8734    * @return {@code true} if the input {@code sequence} is {@code null} ANDno {@code searchStrings} are provided, or

8735    *   the input {@code sequence}ends in any of the provided case-sensitive {@code searchStrings}.

8736    * @since 3.0

8737    */

8738   public static boolean endsWithAny(final CharSequence sequence, finalCharSequence... searchStrings) {

8739       if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {

8740            return false;

8741       }

8742       for (final CharSequence searchString : searchStrings) {

8743            if (endsWith(sequence,searchString)) {

8744                return true;

8745            }

8746       }

8747       return false;

8748   }

8749

8750   /**

8751    * Appends the suffix to the end of the string if the string does not

8752    * already end with the suffix.

8753    *

8754    * @param str The string.

8755    * @param suffix The suffix to append to the end of the string.

8756    * @param ignoreCase Indicates whether the compare should ignore case.

8757    * @param suffixes Additional suffixes that are valid terminators(optional).

8758    *

8759    * @return A new String if suffix was appended, the same stringotherwise.

8760    */

8761   private static String appendIfMissing(final String str, finalCharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes){

8762       if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)){

8763            return str;

8764       }

8765       if (suffixes != null && suffixes.length > 0) {

8766            for (final CharSequence s :suffixes) {

8767                if (endsWith(str, s,ignoreCase)) {

8768                    return str;

8769                }

8770            }

8771       }

8772       return str + suffix.toString();

8773   }

8774

8775   /**

8776    * Appends the suffix to the end of the string if the string does not

8777    * already end with any of the suffixes.

8778    *

8779    * <pre>

8780    * StringUtils.appendIfMissing(null, null) = null

8781    * StringUtils.appendIfMissing("abc", null) = "abc"

8782    * StringUtils.appendIfMissing("", "xyz") ="xyz"

8783    * StringUtils.appendIfMissing("abc", "xyz") ="abcxyz"

8784    * StringUtils.appendIfMissing("abcxyz", "xyz") ="abcxyz"

8785    * StringUtils.appendIfMissing("abcXYZ", "xyz") ="abcXYZxyz"

8786    * </pre>

8787    * <p>With additional suffixes,</p>

8788    * <pre>

8789    * StringUtils.appendIfMissing(null, null, null) = null

8790    * StringUtils.appendIfMissing("abc", null, null) ="abc"

8791    * StringUtils.appendIfMissing("", "xyz", null) ="xyz"

8792    * StringUtils.appendIfMissing("abc", "xyz", newCharSequence[]{null}) = "abcxyz"

8793    * StringUtils.appendIfMissing("abc", "xyz","") = "abc"

8794    * StringUtils.appendIfMissing("abc", "xyz","mno") = "abcxyz"

8795    * StringUtils.appendIfMissing("abcxyz", "xyz","mno") = "abcxyz"

8796    * StringUtils.appendIfMissing("abcmno", "xyz","mno") = "abcmno"

8797    * StringUtils.appendIfMissing("abcXYZ", "xyz","mno") = "abcXYZxyz"

8798    * StringUtils.appendIfMissing("abcMNO", "xyz","mno") = "abcMNOxyz"

8799    * </pre>

8800    *

8801    * @param str The string.

8802    * @param suffix The suffix to append to the end of the string.

8803    * @param suffixes Additional suffixes that are valid terminators.

8804    *

8805    * @return A new String if suffix was appended, the same stringotherwise.

8806    *

8807    * @since 3.2

8808    */

8809   public static String appendIfMissing(final String str, finalCharSequence suffix, final CharSequence... suffixes) {

8810       return appendIfMissing(str, suffix, false, suffixes);

8811   }

8812

8813   /**

8814    * Appends the suffix to the end of the string if the string does not

8815    * already end, case insensitive, with any of the suffixes.

8816    *

8817    * <pre>

8818    * StringUtils.appendIfMissingIgnoreCase(null, null) = null

8819    * StringUtils.appendIfMissingIgnoreCase("abc", null) ="abc"

8820    * StringUtils.appendIfMissingIgnoreCase("", "xyz") ="xyz"

8821    * StringUtils.appendIfMissingIgnoreCase("abc","xyz") = "abcxyz"

8822    * StringUtils.appendIfMissingIgnoreCase("abcxyz","xyz") = "abcxyz"

8823    * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz")= "abcXYZ"

8824    * </pre>

8825    * <p>With additional suffixes,</p>

8826    * <pre>

8827    * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null

8828    * StringUtils.appendIfMissingIgnoreCase("abc", null, null) ="abc"

8829    * StringUtils.appendIfMissingIgnoreCase("", "xyz",null) = "xyz"

8830    * StringUtils.appendIfMissingIgnoreCase("abc","xyz", new CharSequence[]{null}) = "abcxyz"

8831    * StringUtils.appendIfMissingIgnoreCase("abc","xyz", "") = "abc"

8832    * StringUtils.appendIfMissingIgnoreCase("abc","xyz", "mno") = "axyz"

8833    * StringUtils.appendIfMissingIgnoreCase("abcxyz","xyz", "mno") = "abcxyz"

8834    * StringUtils.appendIfMissingIgnoreCase("abcmno","xyz", "mno") = "abcmno"

8835    * StringUtils.appendIfMissingIgnoreCase("abcXYZ","xyz", "mno") = "abcXYZ"

8836    * StringUtils.appendIfMissingIgnoreCase("abcMNO","xyz", "mno") = "abcMNO"

8837    * </pre>

8838    *

8839    * @param str The string.

8840    * @param suffix The suffix to append to the end of the string.

8841    * @param suffixes Additional suffixes that are valid terminators.

8842    *

8843    * @return A new String if suffix was appended, the same stringotherwise.

8844    *

8845    * @since 3.2

8846    */

8847   public static String appendIfMissingIgnoreCase(final String str, finalCharSequence suffix, final CharSequence... suffixes) {

8848       return appendIfMissing(str, suffix, true, suffixes);

8849   }

8850

8851   /**

8852    * Prepends the prefix to the start of the string if the string does not

8853    * already start with any of the prefixes.

8854    *

8855    * @param str The string.

8856    * @param prefix The prefix to prepend to the start of the string.

8857    * @param ignoreCase Indicates whether the compare should ignore case.

8858    * @param prefixes Additional prefixes that are valid (optional).

8859    *

8860    * @return A new String if prefix was prepended, the same stringotherwise.

8861    */

8862   private static String prependIfMissing(final String str, finalCharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes){

8863       if (str == null || isEmpty(prefix) || startsWith(str, prefix,ignoreCase)) {

8864            return str;

8865       }

8866       if (prefixes != null && prefixes.length > 0) {

8867            for (final CharSequence p :prefixes) {

8868                if (startsWith(str, p,ignoreCase)) {

8869                    return str;

8870                }

8871            }

8872       }

8873       return prefix.toString() + str;

8874   }

8875

8876   /**

8877    * Prepends the prefix to the start of the string if the string does not

8878    * already start with any of the prefixes.

8879    *

8880    * <pre>

8881    * StringUtils.prependIfMissing(null, null) = null

8882    * StringUtils.prependIfMissing("abc", null) = "abc"

8883    * StringUtils.prependIfMissing("", "xyz") ="xyz"

8884    * StringUtils.prependIfMissing("abc", "xyz") ="xyzabc"

8885    * StringUtils.prependIfMissing("xyzabc", "xyz") ="xyzabc"

8886    * StringUtils.prependIfMissing("XYZabc", "xyz") ="xyzXYZabc"

8887    * </pre>

8888    * <p>With additional prefixes,</p>

8889    * <pre>

8890    * StringUtils.prependIfMissing(null, null, null) = null

8891    * StringUtils.prependIfMissing("abc", null, null) ="abc"

8892    * StringUtils.prependIfMissing("", "xyz", null) ="xyz"

8893    * StringUtils.prependIfMissing("abc", "xyz", newCharSequence[]{null}) = "xyzabc"

8894     *StringUtils.prependIfMissing("abc", "xyz", "") ="abc"

8895    * StringUtils.prependIfMissing("abc", "xyz","mno") = "xyzabc"

8896    * StringUtils.prependIfMissing("xyzabc", "xyz","mno") = "xyzabc"

8897    * StringUtils.prependIfMissing("mnoabc", "xyz","mno") = "mnoabc"

8898    * StringUtils.prependIfMissing("XYZabc", "xyz","mno") = "xyzXYZabc"

8899    * StringUtils.prependIfMissing("MNOabc", "xyz","mno") = "xyzMNOabc"

8900    * </pre>

8901    *

8902    * @param str The string.

8903    * @param prefix The prefix to prepend to the start of the string.

8904    * @param prefixes Additional prefixes that are valid.

8905    *

8906    * @return A new String if prefix was prepended, the same string otherwise.

8907    *

8908    * @since 3.2

8909    */

8910   public static String prependIfMissing(final String str, finalCharSequence prefix, final CharSequence... prefixes) {

8911       return prependIfMissing(str, prefix, false, prefixes);

8912   }

8913

8914   /**

8915    * Prepends the prefix to the start of the string if the string does not

8916    * already start, case insensitive, with any of the prefixes.

8917    *

8918    * <pre>

8919    * StringUtils.prependIfMissingIgnoreCase(null, null) = null

8920    * StringUtils.prependIfMissingIgnoreCase("abc", null) ="abc"

8921    * StringUtils.prependIfMissingIgnoreCase("", "xyz")= "xyz"

8922    * StringUtils.prependIfMissingIgnoreCase("abc","xyz") = "xyzabc"

8923    * StringUtils.prependIfMissingIgnoreCase("xyzabc","xyz") = "xyzabc"

8924    * StringUtils.prependIfMissingIgnoreCase("XYZabc","xyz") = "XYZabc"

8925    * </pre>

8926    * <p>With additional prefixes,</p>

8927    * <pre>

8928    * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null

8929    * StringUtils.prependIfMissingIgnoreCase("abc", null, null) ="abc"

8930    * StringUtils.prependIfMissingIgnoreCase("", "xyz",null) = "xyz"

8931    * StringUtils.prependIfMissingIgnoreCase("abc","xyz", new CharSequence[]{null}) = "xyzabc"

8932    * StringUtils.prependIfMissingIgnoreCase("abc","xyz", "") = "abc"

8933    * StringUtils.prependIfMissingIgnoreCase("abc","xyz", "mno") = "xyzabc"

8934    * StringUtils.prependIfMissingIgnoreCase("xyzabc","xyz", "mno") = "xyzabc"

8935    * StringUtils.prependIfMissingIgnoreCase("mnoabc","xyz", "mno") = "mnoabc"

8936    * StringUtils.prependIfMissingIgnoreCase("XYZabc","xyz", "mno") = "XYZabc"

8937    * StringUtils.prependIfMissingIgnoreCase("MNOabc","xyz", "mno") = "MNOabc"

8938    * </pre>

8939    *

8940    * @param str The string.

8941    * @param prefix The prefix to prepend to the start of the string.

8942    * @param prefixes Additional prefixes that are valid (optional).

8943    *

8944    * @return A new String if prefix was prepended, the same stringotherwise.

8945    *

8946    * @since 3.2

8947    */

8948   public static String prependIfMissingIgnoreCase(final String str, finalCharSequence prefix, final CharSequence... prefixes) {

8949       return prependIfMissing(str, prefix, true, prefixes);

8950   }

8951

8952   /**

8953    * Converts a <code>byte[]</code> to a String using thespecified character encoding.

8954    *

8955    * @param bytes

8956    *            the byte array toread from

8957    * @param charsetName

8958    *            the encoding to use,if null then use the platform default

8959    * @return a new String

8960    * @throws UnsupportedEncodingException

8961    *             If the named charsetis not supported

8962    * @throws NullPointerException

8963    *             if the input is null

8964    * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)}instead of String constants in your code

8965    * @since 3.1

8966    */

8967   @Deprecated

8968   public static String toString(final byte[] bytes, final StringcharsetName) throws UnsupportedEncodingException {

8969       return charsetName != null ? new String(bytes, charsetName) : newString(bytes, Charset.defaultCharset());

8970   }

8971

8972   /**

8973    * Converts a <code>byte[]</code> to a String using thespecified character encoding.

8974    *

8975    * @param bytes

8976    *            the byte array toread from

8977    * @param charset

8978    *            the encoding to use,if null then use the platform default

8979    * @return a new String

8980    * @throws NullPointerException

8981    *             if {@code bytes} isnull

8982    * @since 3.2

8983    * @since 3.3 No longer throws {@link UnsupportedEncodingException}.

8984    */

8985   public static String toEncodedString(final byte[] bytes, final Charsetcharset) {

8986       return new String(bytes, charset != null ? charset :Charset.defaultCharset());

8987   }

8988

8989   /**

8990    * <p>

8991    * Wraps a string with a char.

8992    * </p>

8993    *

8994    * <pre>

8995    * StringUtils.wrap(null, *)       = null

8996    * StringUtils.wrap("", *)          = ""

8997    * StringUtils.wrap("ab", '\0')     = "ab"

8998    * StringUtils.wrap("ab", 'x')      = "xabx"

8999    * StringUtils.wrap("ab", '\'')     = "'ab'"

9000    * StringUtils.wrap("\"ab\"", '\"') ="\"\"ab\"\""

9001    * </pre>

9002    *

9003    * @param str

9004    *            the string to bewrapped, may be {@code null}

9005    * @param wrapWith

9006    *            the char that willwrap {@code str}

9007    * @return the wrapped string, or {@code null} if {@code str==null}

9008    * @since 3.4

9009    */

9010   public static String wrap(final String str, final char wrapWith) {

9011

9012       if (isEmpty(str) || wrapWith == CharUtils.NUL) {

9013            return str;

9014       }

9015

9016       return wrapWith + str + wrapWith;

9017   }

9018

9019   /**

9020    * <p>

9021    * Wraps a String with another String.

9022    * </p>

9023    *

9024    * <p>

9025    * A {@code null} input String returns {@code null}.

9026    * </p>

9027    *

9028    * <pre>

9029    * StringUtils.wrap(null, *)        = null

9030    * StringUtils.wrap("", *)           = ""

9031    * StringUtils.wrap("ab", null)      = "ab"

9032    * StringUtils.wrap("ab", "x")       = "xabx"

9033    * StringUtils.wrap("ab", "\"")      = "\"ab\""

9034    * StringUtils.wrap("\"ab\"","\"")  ="\"\"ab\"\""

9035    * StringUtils.wrap("ab", "'")       = "'ab'"

9036    * StringUtils.wrap("'abcd'", "'")   = "''abcd''"

9037    * StringUtils.wrap("\"abcd\"", "'") ="'\"abcd\"'"

9038    * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""

9039    * </pre>

9040    *

9041    * @param str

9042    *            the String to bewrapper, may be null

9043    * @param wrapWith

9044    *            the String that willwrap str

9045    * @return wrapped String, {@code null} if null String input

9046    * @since 3.4

9047    */

9048   public static String wrap(final String str, final String wrapWith) {

9049

9050       if (isEmpty(str) || isEmpty(wrapWith)) {

9051            return str;

9052       }

9053

9054       return wrapWith.concat(str).concat(wrapWith);

9055   }

9056

9057   /**

9058    * <p>

9059    * Wraps a string with a char if that char is missing from the start orend of the given string.

9060    * </p>

9061    *

9062    * <pre>

9063    * StringUtils.wrap(null, *)       = null

9064    * StringUtils.wrap("", *)          = ""

9065    * StringUtils.wrap("ab", '\0')     = "ab"

9066    * StringUtils.wrap("ab", 'x')      = "xabx"

9067    * StringUtils.wrap("ab", '\'')     = "'ab'"

9068    * StringUtils.wrap("\"ab\"", '\"') ="\"ab\""

9069    * StringUtils.wrap("/", '/') = "/"

9070    * StringUtils.wrap("a/b/c", '/')  = "/a/b/c/"

9071    * StringUtils.wrap("/a/b/c", '/')  = "/a/b/c/"

9072    * StringUtils.wrap("a/b/c/", '/')  = "/a/b/c/"

9073    * </pre>

9074    *

9075    * @param str

9076    *            the string to be wrapped,may be {@code null}

9077    * @param wrapWith

9078    *            the char that willwrap {@code str}

9079    * @return the wrapped string, or {@code null} if {@code str==null}

9080    * @since 3.5

9081    */

9082   public static String wrapIfMissing(final String str, final charwrapWith) {

9083       if (isEmpty(str) || wrapWith == CharUtils.NUL) {

9084            return str;

9085       }

9086       final StringBuilder builder = new StringBuilder(str.length() + 2);

9087       if (str.charAt(0) != wrapWith) {

9088            builder.append(wrapWith);

9089       }

9090       builder.append(str);

9091       if (str.charAt(str.length() - 1) != wrapWith) {

9092            builder.append(wrapWith);

9093       }

9094       return builder.toString();

9095   }

9096

9097   /**

9098    * <p>

9099    * Wraps a string with a string if that string is missing from the startor end of the given string.

9100    * </p>

9101    *

9102    * <pre>

9103    * StringUtils.wrap(null, *)        = null

9104    * StringUtils.wrap("", *)           = ""

9105    * StringUtils.wrap("ab", null)      = "ab"

9106    * StringUtils.wrap("ab", "x")       = "xabx"

9107    * StringUtils.wrap("ab", "\"")      = "\"ab\""

9108    * StringUtils.wrap("\"ab\"","\"")  ="\"ab\""

9109    * StringUtils.wrap("ab", "'")       = "'ab'"

9110    * StringUtils.wrap("'abcd'", "'")   = "'abcd'"

9111    * StringUtils.wrap("\"abcd\"", "'") ="'\"abcd\"'"

9112    * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""

9113    * StringUtils.wrap("/", "/")  = "/"

9114    * StringUtils.wrap("a/b/c", "/")  = "/a/b/c/"

9115    * StringUtils.wrap("/a/b/c", "/")  = "/a/b/c/"

9116    * StringUtils.wrap("a/b/c/", "/")  = "/a/b/c/"

9117    * </pre>

9118    *

9119    * @param str

9120    *            the string to bewrapped, may be {@code null}

9121    * @param wrapWith

9122    *            the char that willwrap {@code str}

9123    * @return the wrapped string, or {@code null} if {@code str==null}

9124    * @since 3.5

9125    */

9126   public static String wrapIfMissing(final String str, final StringwrapWith) {

9127       if (isEmpty(str) || isEmpty(wrapWith)) {

9128            return str;

9129       }

9130       final StringBuilder builder = new StringBuilder(str.length() +wrapWith.length() + wrapWith.length());

9131       if (!str.startsWith(wrapWith)) {

9132            builder.append(wrapWith);

9133       }

9134       builder.append(str);

9135       if (!str.endsWith(wrapWith)) {

9136            builder.append(wrapWith);

9137       }

9138       return builder.toString();

9139   }

9140

9141   /**

9142    * <p>

9143    * Unwraps a given string from anther string.

9144    * </p>

9145    *

9146    * <pre>

9147    * StringUtils.unwrap(null, null)        = null

9148    * StringUtils.unwrap(null, "")           = null

9149    * StringUtils.unwrap(null, "1")          = null

9150    * StringUtils.unwrap("\'abc\'", "\'")    = "abc"

9151    * StringUtils.unwrap("\"abc\"","\"")    = "abc"

9152    * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"

9153    * StringUtils.unwrap("A", "#")           = "A"

9154    * StringUtils.unwrap("#A", "#")          = "#A"

9155    * StringUtils.unwrap("A#", "#")          = "A#"

9156    * </pre>

9157    *

9158    * @param str

9159    *          the String to beunwrapped, can be null

9160    * @param wrapToken

9161    *          the String used tounwrap

9162    * @return unwrapped String or the original string

9163    *          if it is not quotedproperly with the wrapToken

9164    * @since 3.6

9165    */

9166   public static String unwrap(final String str, final String wrapToken) {

9167       if (isEmpty(str) || isEmpty(wrapToken)) {

9168            return str;

9169       }

9170

9171       if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) {

9172            final int startIndex =str.indexOf(wrapToken);

9173            final int endIndex =str.lastIndexOf(wrapToken);

9174            final int wrapLength =wrapToken.length();

9175            if (startIndex != -1 &&endIndex != -1) {

9176                return str.substring(startIndex+ wrapLength, endIndex);

9177            }

9178       }

9179

9180       return str;

9181   }

9182

9183   /**

9184    * <p>

9185    * Unwraps a given string from a character.

9186    * </p>

9187    *

9188    * <pre>

9189    * StringUtils.unwrap(null, null)        = null

9190    * StringUtils.unwrap(null, '\0')        = null

9191    * StringUtils.unwrap(null, '1')         = null

9192    * StringUtils.unwrap("\'abc\'", '\'')    = "abc"

9193    * StringUtils.unwrap("AABabcBAA", 'A')  = "ABabcBA"

9194    * StringUtils.unwrap("A", '#')           = "A"

9195    * StringUtils.unwrap("#A", '#')          = "#A"

9196    * StringUtils.unwrap("A#", '#')          = "A#"

9197    * </pre>

9198    *

9199    * @param str

9200    *          the String to beunwrapped, can be null

9201    * @param wrapChar

9202    *          the character used tounwrap

9203    * @return unwrapped String or the original string

9204    *          if it is not quotedproperly with the wrapChar

9205    * @since 3.6

9206    */

9207   public static String unwrap(final String str, final char wrapChar) {

9208       if (isEmpty(str) || wrapChar == CharUtils.NUL) {

9209            return str;

9210       }

9211

9212       if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) ==wrapChar) {

9213            final int startIndex = 0;

9214            final int endIndex = str.length() -1;

9215            if (startIndex != -1 &&endIndex != -1) {

9216                return str.substring(startIndex+ 1, endIndex);

9217            }

9218       }

9219

9220       return str;

9221   }

9222

9223   /**

9224    * <p>Converts a {@code CharSequence} into an array of codepoints.</p>

9225    *

9226    * <p>Valid pairs of surrogate code units will be converted into asingle supplementary

9227    * code point. Isolated surrogate code units (i.e. a high surrogate notfollowed by a low surrogate or

9228    * a low surrogate not preceeded by a high surrogate) will be returnedas-is.</p>

9229    *

9230    * <pre>

9231    * StringUtils.toCodePoints(null)  =  null

9232    * StringUtils.toCodePoints("")     = []  // empty array

9233    * </pre>

9234    *

9235    * @param str the character sequence to convert

9236    * @return an array of code points

9237    * @since 3.6

9238    */

9239   public static int[] toCodePoints(CharSequence str) {

9240       if (str == null) {

9241            return null;

9242       }

9243       if (str.length() == 0) {

9244            return ArrayUtils.EMPTY_INT_ARRAY;

9245       }

9246

9247       String s = str.toString();

9248       int[] result = new int[s.codePointCount(0, s.length())];

9249       int index = 0;

9250       for (int i = 0; i < result.length; i++) {

9251            result[i] = s.codePointAt(index);

9252            index += Character.charCount(result[i]);

9253       }

9254       return result;

9255   }

9256}

 

原创粉丝点击