Return-Path: X-Original-To: apmail-flex-commits-archive@www.apache.org Delivered-To: apmail-flex-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 227E4100DD for ; Sat, 7 Mar 2015 12:06:55 +0000 (UTC) Received: (qmail 58895 invoked by uid 500); 7 Mar 2015 12:06:54 -0000 Delivered-To: apmail-flex-commits-archive@flex.apache.org Received: (qmail 58767 invoked by uid 500); 7 Mar 2015 12:06:54 -0000 Mailing-List: contact commits-help@flex.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@flex.apache.org Delivered-To: mailing list commits@flex.apache.org Received: (qmail 58615 invoked by uid 99); 7 Mar 2015 12:06:54 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 07 Mar 2015 12:06:54 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 6D2F1E042A; Sat, 7 Mar 2015 12:06:54 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cdutz@apache.org To: commits@flex.apache.org Date: Sat, 07 Mar 2015 12:06:57 -0000 Message-Id: In-Reply-To: <0179febeb78b4335a3d6fbf7ffdb3d31@git.apache.org> References: <0179febeb78b4335a3d6fbf7ffdb3d31@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [04/24] git commit: [flex-utilities] [refs/heads/feature/pmd-5.2-language-module] - Initial commit of the PMD language module for Apache Flex http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/ff722d6f/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD181.as ---------------------------------------------------------------------- diff --git a/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD181.as b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD181.as new file mode 100644 index 0000000..bd94928 --- /dev/null +++ b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD181.as @@ -0,0 +1,2344 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// +package org.as3commons.lang { + + /** + *

Methods in this class give sample code to explain their operation. + * The symbol * is used to indicate any input + * including null.

+ * + * @author Steffen Leistner + * @author Christophe Herreman + */ + public class StringUtils { // NO PMD TooManyFunction TooManyPublic + + /** + * The empty String "" + */ + private static const EMPTY:String = ''; + + /** + * Represents a failed index search. + */ + private static const INDEX_NOT_FOUND:int = -1; + + /** + * The control character code + */ + private static const WHITE:uint = 32; + + /** + *

The maximum size to which the padding constant(s) can expand.

+ */ + private static const PAD_LIMIT:uint = 8192; + + /** + *

Returns a simple Initials like string.

+ * + * StringUtils.toInitials("stringutils") = s + * StringUtils.toInitials("stringUtils") = su + * StringUtils.toInitials("stringUtilsTest") = sut + */ + public static function toInitials(str:String):String { + if (isEmpty(str)) { + return str; + } + return str.match(/[A-Z]/g).join('').toLowerCase(); + } + + /** + *

Removes one newline from end of a String if it's there, + * otherwise leave it alone. A newline is "\n", + * "\r", or "\r\n".

+ * + *
+		 * StringUtils.chomp(null)          = null
+		 * StringUtils.chomp("")            = ""
+		 * StringUtils.chomp("abc \r")      = "abc "
+		 * StringUtils.chomp("abc\n")       = "abc"
+		 * StringUtils.chomp("abc\r\n")     = "abc"
+		 * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
+		 * StringUtils.chomp("abc\n\r")     = "abc\n"
+		 * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
+		 * StringUtils.chomp("\r")          = ""
+		 * StringUtils.chomp("\n")          = ""
+		 * StringUtils.chomp("\r\n")        = ""
+		 * 
+ * + * @param str the String to chomp a newline from, may be null + * @return String without newline, null if null String input + */ + public static function chomp(str:String):String { + return chompString(str, '(\r\n|\r|\n)'); + } + + /** + *

Removes separator from the end of + * str if it's there, otherwise leave it alone.

+ * + *

It now more closely matches Perl chomp. + * For the previous behavior, use #substringBeforeLast(String, String). + * This method uses #endsWith(String).

+ * + *
+		 * StringUtils.chompString(null, *)         = null
+		 * StringUtils.chompString("", *)           = ""
+		 * StringUtils.chompString("foobar", "bar") = "foo"
+		 * StringUtils.chompString("foobar", "baz") = "foobar"
+		 * StringUtils.chompString("foo", "foo")    = ""
+		 * StringUtils.chompString("foo ", "foo")   = "foo "
+		 * StringUtils.chompString(" foo", "foo")   = " "
+		 * StringUtils.chompString("foo", "foooo")  = "foo"
+		 * StringUtils.chompString("foo", "")       = "foo"
+		 * StringUtils.chompString("foo", null)     = "foo"
+		 * 
+ * + * @param str the String to chomp from, may be null + * @param separator separator String, may be null + * @return String without trailing separator, null if null String input + */ + public static function chompString(str:String, separator:String):String { + if (isEmpty(str) || separator == null) { + return str; + } + return str.replace(new RegExp(separator + '$', ''), '') + } + + /** + *

Removes control characters(char <= 32) from both + * ends of this String, handling null by returning + * null.

+ * + *

Trim removes start and end characters <= 32. + * To strip whitespace use #strip(String).

+ * + *

To trim your choice of characters, use the + * #strip(String, String) methods.

+ * + *
+		 * StringUtils.trim(null)          = null
+		 * StringUtils.trim("")            = ""
+		 * StringUtils.trim("     ")       = ""
+		 * StringUtils.trim("abc")         = "abc"
+		 * StringUtils.trim("    abc    ") = "abc"
+		 * 
+ * + * @param str the String to be trimmed, may be null + * @return the trimmed string, null if null String input + */ + public static function trim(str:String):String { + if (str == null) { + return null; + } + return str.replace(/^\s*/, '').replace(/\s*$/, ''); + } + + /** + *

Deletes all 'space' characters from a String as defined by + * + *

+		 * StringUtils.deleteSpaces(null)           = null
+		 * StringUtils.deleteSpaces("")             = ""
+		 * StringUtils.deleteSpaces("abc")          = "abc"
+		 * StringUtils.deleteSpaces(" \tabc \n ") = " abc  "
+		 * StringUtils.deleteSpaces("a\nb\tc     ") = "abc     "
+		 * 
+ * + *

Spaces are defined as {'\t', '\r', '\n', '\b'} + * in line with the deprecated isSpace method.

+ * + * @param str the String to delete spaces from, may be null + * @return the String without 'spaces', null if null String input + */ + public static function deleteSpaces(str:String):String { + return deleteFromString(str, /\t|\r|\n|\b/g); + } + + /** + *

Deletes all whitespaces from a String.

+ * + *
+		 * StringUtils.deleteWhitespace(null)         = null
+		 * StringUtils.deleteWhitespace("")           = ""
+		 * StringUtils.deleteWhitespace("abc")        = "abc"
+		 * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
+		 * 
+ * + * @param str the String to delete whitespace from, may be null + * @return the String without whitespaces, null if null String input + */ + public static function deleteWhitespace(str:String):String { + return deleteFromString(str, /\s/g); + } + + private static function deleteFromString(str:String, pattern:RegExp):String { + if (isEmpty(str)) { + return str; + } + return str.replace(pattern, ''); + } + + /** + *

Gets the leftmost len characters of a String.

+ * + *

If len characters are not available, or the + * String is null, the String will be returned without + * an exception. An exception is thrown if len is negative.

+ * + *
+		 * StringUtils.left(null, *)    = null
+		 * StringUtils.left(*, -ve)     = ""
+		 * StringUtils.left("", *)      = ""
+		 * StringUtils.left("abc", 0)   = ""
+		 * StringUtils.left("abc", 2)   = "ab"
+		 * StringUtils.left("abc", 4)   = "abc"
+		 * 
+ * + * @param str the String to get the leftmost characters from, may be null + * @param len the length of the required String, must be zero or positive + * @return the leftmost characters, null if null String input + */ + public static function left(str:String, len:int):String { + if (str == null) { + return null; + } + + if (len < 0) { + return EMPTY; + } + + if (str.length <= len) { + return str; + } + return str.substring(0, len); + } + + /** + *

Centers a String in a larger String of size size. + * Uses a supplied String as the value to pad the String with.

+ * + *

If the size is less than the String length, the String is returned. + * A null String returns null. + * A negative size is treated as zero.

+ * + *
+		 * StringUtils.center(null, *, *)     = null
+		 * StringUtils.center("", 4, " ")     = "    "
+		 * StringUtils.center("ab", -1, " ")  = "ab"
+		 * StringUtils.center("ab", 4, " ")   = " ab "
+		 * StringUtils.center("abcd", 2, " ") = "abcd"
+		 * StringUtils.center("a", 4, " ")    = " a  "
+		 * StringUtils.center("a", 4, "yz")   = "yayz"
+		 * StringUtils.center("abc", 7, null) = "  abc  "
+		 * StringUtils.center("abc", 7, "")   = "  abc  "
+		 * 
+ * + * @param str the String to center, may be null + * @param size the int size of new String, negative treated as zero + * @param padStr the String to pad the new String with, must not be null or empty + * @return centered String, null if null String input + */ + public static function center(str:String, size:int, padStr:String):String { + if (str == null || size <= 0) { + return str; + } + + if (isEmpty(padStr)) { + padStr = " "; + } + var strLen:int = str.length; + var pads:int = size - strLen; + + if (pads <= 0) { + return str; + } + str = leftPad(str, strLen + pads / 2, padStr); + str = rightPad(str, size, padStr); + + return str; + } + + /** + *

Left pad a String with a specified String.

+ * + *

Pad to a size of size.

+ * + *
+		 * StringUtils.leftPad(null, *, *)      = null
+		 * StringUtils.leftPad("", 3, "z")      = "zzz"
+		 * StringUtils.leftPad("bat", 3, "yz")  = "bat"
+		 * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
+		 * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
+		 * StringUtils.leftPad("bat", 1, "yz")  = "bat"
+		 * StringUtils.leftPad("bat", -1, "yz") = "bat"
+		 * StringUtils.leftPad("bat", 5, null)  = "  bat"
+		 * StringUtils.leftPad("bat", 5, "")    = "  bat"
+		 * 
+ * + * @param str the String to pad out, may be null + * @param size the size to pad to + * @param padStr the String to pad with, null or empty treated as single space + * @return left padded String or original String if no padding is necessary, + * null if null String input + */ + public static function leftPad(str:String, size:int, padStr:String):String { + if (str == null) { + return null; + } + + if (isEmpty(padStr)) { + padStr = " "; + } + var padLen:int = padStr.length; + var strLen:int = str.length; + var pads:int = size - strLen; + + if (pads <= 0) { + return str; // returns original String when possible + } + + if (padLen == 1 && pads <= PAD_LIMIT) { + return leftPadChar(str, size, padStr.charAt(0)); + } + + if (pads == padLen) { + return padStr.concat(str); + } else if (pads < padLen) { + return padStr.substring(0, pads).concat(str); + } else { + var padding:Array = []; + var padChars:Array = padStr.split(""); + + for (var i:int = 0; i < pads; i++) { + padding[i] = padChars[i % padLen]; + } + return padding.join("").concat(str); + } + } + + /** + *

Left pad a String with a specified character.

+ * + *

Pad to a size of size.

+ * + *
+		 * StringUtils.leftPadChar(null, *, *)     = null
+		 * StringUtils.leftPadChar("", 3, 'z')     = "zzz"
+		 * StringUtils.leftPadChar("bat", 3, 'z')  = "bat"
+		 * StringUtils.leftPadChar("bat", 5, 'z')  = "zzbat"
+		 * StringUtils.leftPadChar("bat", 1, 'z')  = "bat"
+		 * StringUtils.leftPadChar("bat", -1, 'z') = "bat"
+		 * 
+ * + * @param str the String to pad out, may be null + * @param size the size to pad to + * @param padChar the character to pad with + * @return left padded String or original String if no padding is necessary, + * null if null String input + */ + public static function leftPadChar(str:String, size:int, padChar:String):String { + if (str == null) { + return null; + } + var pads:int = size - str.length; + + if (pads <= 0) { + return str; // returns original String when possible + } + + if (pads > PAD_LIMIT) { + return leftPad(str, size, padChar); + } + return padding(pads, padChar).concat(str); + } + + /** + *

Right pad a String with a specified String.

+ * + *

The String is padded to the size of size.

+ * + *
+		 * StringUtils.rightPad(null, *, *)      = null
+		 * StringUtils.rightPad("", 3, "z")      = "zzz"
+		 * StringUtils.rightPad("bat", 3, "yz")  = "bat"
+		 * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
+		 * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
+		 * StringUtils.rightPad("bat", 1, "yz")  = "bat"
+		 * StringUtils.rightPad("bat", -1, "yz") = "bat"
+		 * StringUtils.rightPad("bat", 5, null)  = "bat  "
+		 * StringUtils.rightPad("bat", 5, "")    = "bat  "
+		 * 
+ * + * @param str the String to pad out, may be null + * @param size the size to pad to + * @param padStr the String to pad with, null or empty treated as single space + * @return right padded String or original String if no padding is necessary, + * null if null String input + */ + public static function rightPad(str:String, size:int, padStr:String):String { + if (str == null) { + return null; + } + + if (isEmpty(padStr)) { + padStr = " "; + } + var padLen:int = padStr.length; + var strLen:int = str.length; + var pads:int = size - strLen; + + if (pads <= 0) { + return str; // returns original String when possible + } + + if (padLen == 1 && pads <= PAD_LIMIT) { + return rightPadChar(str, size, padStr.charAt(0)); + } + + if (pads == padLen) { + return str.concat(padStr); + } else if (pads < padLen) { + return str.concat(padStr.substring(0, pads)); + } else { + var padding:Array = []; + var padChars:Array = padStr.split(""); + + for (var i:int = 0; i < pads; i++) { + padding[i] = padChars[i % padLen]; + } + return str.concat(padding.join("")); + } + } + + /** + *

Right pad a String with a specified character.

+ * + *

The String is padded to the size of size.

+ * + *
+		 * StringUtils.rightPadChar(null, *, *)     = null
+		 * StringUtils.rightPadChar("", 3, 'z')     = "zzz"
+		 * StringUtils.rightPadChar("bat", 3, 'z')  = "bat"
+		 * StringUtils.rightPadChar("bat", 5, 'z')  = "batzz"
+		 * StringUtils.rightPadChar("bat", 1, 'z')  = "bat"
+		 * StringUtils.rightPadChar("bat", -1, 'z') = "bat"
+		 * 
+ * + * @param str the String to pad out, may be null + * @param size the size to pad to + * @param padChar the character to pad with + * @return right padded String or original String if no padding is necessary, + * null if null String input + */ + public static function rightPadChar(str:String, size:int, padChar:String):String { + if (str == null) { + return null; + } + var pads:int = size - str.length; + + if (pads <= 0) { + return str; // returns original String when possible + } + + if (pads > PAD_LIMIT) { + return rightPad(str, size, padChar); + } + return str.concat(padding(pads, padChar)); + } + + /** + *

Returns padding using the specified delimiter repeated + * to a given length.

+ * + *
+		 * StringUtils.padding(0, 'e')  = ""
+		 * StringUtils.padding(3, 'e')  = "eee"
+		 * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
+		 * 
+ * + * @param repeat number of times to repeat delim + * @param padChar character to repeat + * @return String with repeated character + */ + private static function padding(repeat:int, padChar:String):String { + var buffer:String = ''; + + for (var i:int = 0; i < repeat; i++) { + buffer += padChar; + } + return buffer; + } + + /** + *

Replaces all occurrences of a String within another String.

+ * + *

A null reference passed to this method is a no-op.

+ * + *
+		 * StringUtils.replace(null, *, *)        = null
+		 * StringUtils.replace("", *, *)          = ""
+		 * StringUtils.replace("any", null, *)    = "any"
+		 * StringUtils.replace("any", *, null)    = "any"
+		 * StringUtils.replace("any", "", *)      = "any"
+		 * StringUtils.replace("aba", "a", null)  = "aba"
+		 * StringUtils.replace("aba", "a", "")    = "b"
+		 * StringUtils.replace("aba", "a", "z")   = "zbz"
+		 * 
+ * + * @param text text to search and replace in, may be null + * @param pattern the String to search for, may be null + * @param repl the String to replace with, may be null + * @return the text with any replacements processed, + * null if null String input + */ + public static function replace(text:String, pattern:String, repl:String):String { + if (text == null || isEmpty(pattern) || repl == null) { + return text; + } + return text.replace(new RegExp(pattern, 'g'), repl); + } + + /** + *

Replaces a String with another String inside a larger String, + * for the first max values of the search String.

+ * + *

A null reference passed to this method is a no-op.

+ * + *
+		 * StringUtils.replaceTo(null, *, *, *)         = null
+		 * StringUtils.replaceTo("", *, *, *)           = ""
+		 * StringUtils.replaceTo("any", null, *, *)     = "any"
+		 * StringUtils.replaceTo("any", *, null, *)     = "any"
+		 * StringUtils.replaceTo("any", "", *, *)       = "any"
+		 * StringUtils.replaceTo("any", *, *, 0)        = "any"
+		 * StringUtils.replaceTo("abaa", "a", null, -1) = "abaa"
+		 * StringUtils.replaceTo("abaa", "a", "", -1)   = "b"
+		 * StringUtils.replaceTo("abaa", "a", "z", 0)   = "abaa"
+		 * StringUtils.replaceTo("abaa", "a", "z", 1)   = "zbaa"
+		 * StringUtils.replaceTo("abaa", "a", "z", 2)   = "zbza"
+		 * StringUtils.replaceTo("abaa", "a", "z", -1)  = "zbzz"
+		 * 
+ * + * @param text text to search and replace in, may be null + * @param repl the String to search for, may be null + * @param with the String to replace with, may be null + * @param max maximum number of values to replace, or -1 if no maximum + * @return the text with any replacements processed, + * null if null String input + */ + public static function replaceTo(text:String, pattern:String, repl:String, max:int):String { + if (text == null || isEmpty(pattern) || repl == null || max == 0) { + return text; + } + + var buf:String = ""; + var start:int = 0; + var end:int = 0; + + while ((end = text.indexOf(pattern, start)) != -1) { + buf += text.substring(start, end) + repl; + start = end + pattern.length; + + if (--max == 0) { + break; + } + } + return buf += text.substring(start); + } + + /** + *

Replaces a String with another String inside a larger String, once.

+ * + *

A null reference passed to this method is a no-op.

+ * + *
+		 * StringUtils.replaceOnce(null, *, *)        = null
+		 * StringUtils.replaceOnce("", *, *)          = ""
+		 * StringUtils.replaceOnce("any", null, *)    = "any"
+		 * StringUtils.replaceOnce("any", *, null)    = "any"
+		 * StringUtils.replaceOnce("any", "", *)      = "any"
+		 * StringUtils.replaceOnce("aba", "a", null)  = "aba"
+		 * StringUtils.replaceOnce("aba", "a", "")    = "ba"
+		 * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
+		 * 
+ * + * @see #replaceTo(text:String, pattern:String, repl:String, max:int) + * @param text text to search and replace in, may be null + * @param repl the String to search for, may be null + * @param with the String to replace with, may be null + * @return the text with any replacements processed, + * null if null String input + */ + public static function replaceOnce(text:String, pattern:String, repl:String):String { + if (text == null || isEmpty(pattern) || repl == null) { + return text; + } + return text.replace(new RegExp(pattern, ''), repl); + } + + /** + *

Returns either the passed in String, or if the String is + * empty or null, the value of defaultStr.

+ * + *
+		 * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
+		 * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
+		 * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
+		 * 
+ * + * @param str the String to check, may be null + * @param defaultStr the default String to return + * if the input is empty("") or null, may be null + * @return the passed in String, or the default + */ + public static function defaultIfEmpty(str:String, defaultStr:String):String { + return isEmpty(str) ? defaultStr : str; + } + + /** + *

Checks if a String is empty("") or null.

+ * + *
+		 * StringUtils.isEmpty(null)      = true
+		 * StringUtils.isEmpty("")        = true
+		 * StringUtils.isEmpty(" ")       = false
+		 * StringUtils.isEmpty("bob")     = false
+		 * StringUtils.isEmpty("  bob  ") = false
+		 * 
+ * + *

NOTE: This method changed in Lang version 2.0. + * It no longer trims the String. + * That functionality is available in isBlank().

+ * + * @param str the String to check, may be null + * @return true if the String is empty or null + */ + public static function isEmpty(str:String):Boolean { + if (str == null) { + return true; + } + return str.length == 0; + } + + /** + *

Checks if a String is not empty("") and not null.

+ * + *
+		 * StringUtils.isNotEmpty(null)      = false
+		 * StringUtils.isNotEmpty("")        = false
+		 * StringUtils.isNotEmpty(" ")       = true
+		 * StringUtils.isNotEmpty("bob")     = true
+		 * StringUtils.isNotEmpty("  bob  ") = true
+		 * 
+ * + * @param str the String to check, may be null + * @return true if the String is not empty and not null + */ + public static function isNotEmpty(str:String):Boolean { + return !isEmpty(str); + } + + /** + *

Checks if a String is whitespace, empty("") or null.

+ * + *
+		 * StringUtils.isBlank(null)      = true
+		 * StringUtils.isBlank("")        = true
+		 * StringUtils.isBlank(" ")       = true
+		 * StringUtils.isBlank("bob")     = false
+		 * StringUtils.isBlank("  bob  ") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if the String is null, empty or whitespace + */ + public static function isBlank(str:String):Boolean { + return isEmpty(trimToEmpty(str)); + } + + /** + *

Checks if a String is not empty(""), not null + * and not whitespace only.

+ * + *
+		 * StringUtils.isNotBlank(null)      = false
+		 * StringUtils.isNotBlank("")        = false
+		 * StringUtils.isNotBlank(" ")       = false
+		 * StringUtils.isNotBlank("bob")     = true
+		 * StringUtils.isNotBlank("  bob  ") = true
+		 * 
+ * + * @param str the String to check, may be null + * @return true if the String is + * not empty and not null and not whitespace + */ + public static function isNotBlank(str:String):Boolean { + return !isBlank(str); + } + + /** + *

Removes control characters (char <= 32) from both + * ends of this String returning null if the String is + * empty ("") after the trim or if it is null. + * + *

The String is trimmed using #trim(). + * Trim removes start and end characters <= 32.

+ * + *
+		 * StringUtils.trimToNull(null)          = null
+		 * StringUtils.trimToNull("")            = null
+		 * StringUtils.trimToNull("     ")       = null
+		 * StringUtils.trimToNull("abc")         = "abc"
+		 * StringUtils.trimToNull("    abc    ") = "abc"
+		 * 
+ * + * @param str the String to be trimmed, may be null + * @return the trimmed String, + * null if only chars <= 32, empty or null String input + */ + public static function trimToNull(str:String):String { + var trimedString:String = trim(str); + return isEmpty(trimedString) ? null : trimedString; + } + + /** + *

Removes control characters (char <= 32) from both + * ends of this String returning an empty String ("") if the String + * is empty ("") after the trim or if it is null. + * + *

The String is trimmed using #trim(). + * Trim removes start and end characters <= 32. + * To strip whitespace use #stripToEmpty(String).

+ * + *
+		 * StringUtils.trimToEmpty(null)          = ""
+		 * StringUtils.trimToEmpty("")            = ""
+		 * StringUtils.trimToEmpty("     ")       = ""
+		 * StringUtils.trimToEmpty("abc")         = "abc"
+		 * StringUtils.trimToEmpty("    abc    ") = "abc"
+		 * 
+ * + * @param str the String to be trimmed, may be null + * @return the trimmed String, or an empty String if null input + */ + public static function trimToEmpty(str:String):String { + return str == null ? EMPTY : trim(str); + } + + /** + *

Capitalizes a String changing the first letter to title case. + * No other letters are changed.

+ * + * A null input String returns null.

+ * + *
+		 * StringUtils.capitalize(null)  = null
+		 * StringUtils.capitalize("")    = ""
+		 * StringUtils.capitalize("cat") = "Cat"
+		 * StringUtils.capitalize("cAt") = "CAt"
+		 * 
+ * + * @param str the String to capitalize, may be null + * @return the capitalized String, null if null String input + * @see titleize(String) + * @see #uncapitalize(String) + */ + public static function capitalize(str:String):String { + if (isEmpty(str)) { + return str; + } + return str.charAt(0).toUpperCase() + str.substring(1); + } + + /** + *

Uncapitalizes a String changing the first letter to title case. + * No other letters are changed.

+ * + *
+		 * StringUtils.uncapitalize(null)  = null
+		 * StringUtils.uncapitalize("")    = ""
+		 * StringUtils.uncapitalize("Cat") = "cat"
+		 * StringUtils.uncapitalize("CAT") = "cAT"
+		 * 
+ * + * @param str the String to uncapitalize, may be null + * @return the uncapitalized String, null if null String input + * @see #capitalize(String) + */ + public static function uncapitalize(str:String):String { + if (isEmpty(str)) { + return str; + } + return str.charAt(0).toLowerCase() + str.substring(1); + } + + /** + *

Capitalizes all the words and replaces some characters in + * the string to create a nicer looking title. + * Titleize is meant for creating pretty output.

+ * + *
+		 * StringUtils.titleize(null)  = null
+		 * StringUtils.titleize("")    = ""
+		 * StringUtils.titleize("man from the boondocks") = "Man From The Boondocks"
+		 * StringUtils.titleize("man from THE bOOndocks") = "Man From The Boondocks"
+		 * 
+ * + * @param str the String to uncapitalize, may be null + * @return the uncapitalized String, null if null String input + * @see #capitalize(String) + */ + public static function titleize(str:String):String { + if (isEmpty(str)) { + return str; + } + var words:Array = str.toLowerCase().split(' '); + + for (var i:int = 0; i < words.length; i++) { + words[i] = capitalize(words[i]); + } + return words.join(' '); + } + + /** + *

Gets the substring after the first occurrence of a separator. + * The separator is not returned.

+ * + *

A null string input will return null. + * An empty("") string input will return the empty string. + * A null separator will return the empty string if the + * input string is not null.

+ * + *
+		 * StringUtils.substringAfter(null, *)      = null
+		 * StringUtils.substringAfter("", *)        = ""
+		 * StringUtils.substringAfter(*, null)      = ""
+		 * StringUtils.substringAfter("abc", "a")   = "bc"
+		 * StringUtils.substringAfter("abcba", "b") = "cba"
+		 * StringUtils.substringAfter("abc", "c")   = ""
+		 * StringUtils.substringAfter("abc", "d")   = ""
+		 * StringUtils.substringAfter("abc", "")    = "abc"
+		 * 
+ * + * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring after the first occurrence of the separator, + * null if null String input + */ + public static function substringAfter(str:String, separator:String):String { + if (isEmpty(str)) { + return str; + } + + if (separator == null) { + return EMPTY; + } + var pos:int = str.indexOf(separator); + + if (pos == INDEX_NOT_FOUND) { + return EMPTY; + } + return str.substring(pos + separator.length); + } + + /** + *

Gets the substring after the last occurrence of a separator. + * The separator is not returned.

+ * + *

A null string input will return null. + * An empty("") string input will return the empty string. + * An empty or null separator will return the empty string if + * the input string is not null.

+ * + *
+		 * StringUtils.substringAfterLast(null, *)      = null
+		 * StringUtils.substringAfterLast("", *)        = ""
+		 * StringUtils.substringAfterLast(*, "")        = ""
+		 * StringUtils.substringAfterLast(*, null)      = ""
+		 * StringUtils.substringAfterLast("abc", "a")   = "bc"
+		 * StringUtils.substringAfterLast("abcba", "b") = "a"
+		 * StringUtils.substringAfterLast("abc", "c")   = ""
+		 * StringUtils.substringAfterLast("a", "a")     = ""
+		 * StringUtils.substringAfterLast("a", "z")     = ""
+		 * 
+ * + * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring after the last occurrence of the separator, + * null if null String input + */ + public static function substringAfterLast(str:String, separator:String):String { + if (isEmpty(str)) { + return str; + } + + if (isEmpty(separator)) { + return EMPTY; + } + var pos:int = str.lastIndexOf(separator); + + if (pos == INDEX_NOT_FOUND || pos == (str.length - separator.length)) { + return EMPTY; + } + return str.substring(pos + separator.length); + } + + /** + *

Gets the substring before the first occurrence of a separator. + * The separator is not returned.

+ * + *

A null string input will return null. + * An empty("") string input will return the empty string. + * A null separator will return the input string.

+ * + *
+		 * StringUtils.substringBefore(null, *)      = null
+		 * StringUtils.substringBefore("", *)        = ""
+		 * StringUtils.substringBefore("abc", "a")   = ""
+		 * StringUtils.substringBefore("abcba", "b") = "a"
+		 * StringUtils.substringBefore("abc", "c")   = "ab"
+		 * StringUtils.substringBefore("abc", "d")   = "abc"
+		 * StringUtils.substringBefore("abc", "")    = ""
+		 * StringUtils.substringBefore("abc", null)  = "abc"
+		 * 
+ * + * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring before the first occurrence of the separator, + * null if null String input + */ + public static function substringBefore(str:String, separator:String):String { + if (isEmpty(str) || separator == null) { + return str; + } + + if (separator.length == 0) { + return EMPTY; + } + var pos:int = str.indexOf(separator); + + if (pos == INDEX_NOT_FOUND) { + return str; + } + return str.substring(0, pos); + } + + /** + *

Gets the substring before the last occurrence of a separator. + * The separator is not returned.

+ * + *

A null string input will return null. + * An empty("") string input will return the empty string. + * An empty or null separator will return the input string.

+ * + *
+		 * StringUtils.substringBeforeLast(null, *)      = null
+		 * StringUtils.substringBeforeLast("", *)        = ""
+		 * StringUtils.substringBeforeLast("abcba", "b") = "abc"
+		 * StringUtils.substringBeforeLast("abc", "c")   = "ab"
+		 * StringUtils.substringBeforeLast("a", "a")     = ""
+		 * StringUtils.substringBeforeLast("a", "z")     = "a"
+		 * StringUtils.substringBeforeLast("a", null)    = "a"
+		 * StringUtils.substringBeforeLast("a", "")      = "a"
+		 * 
+ * + * @param str the String to get a substring from, may be null + * @param separator the String to search for, may be null + * @return the substring before the last occurrence of the separator, + * null if null String input + */ + public static function substringBeforeLast(str:String, separator:String):String { + if (isEmpty(str) || isEmpty(separator)) { + return str; + } + var pos:int = str.lastIndexOf(separator); + + if (pos == INDEX_NOT_FOUND) { + return str; + } + return str.substring(0, pos); + } + + /** + *

Gets the String that is nested in between two Strings. + * Only the first match is returned.

+ * + *

A null input String returns null. + * A null open/close returns null(no match). + * An empty("") open/close returns an empty string.

+ * + *
+		 * StringUtils.substringBetween(null, *, *)          = null
+		 * StringUtils.substringBetween("", "", "")          = ""
+		 * StringUtils.substringBetween("", "", "tag")       = null
+		 * StringUtils.substringBetween("", "tag", "tag")    = null
+		 * StringUtils.substringBetween("yabcz", null, null) = null
+		 * StringUtils.substringBetween("yabcz", "", "")     = ""
+		 * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
+		 * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
+		 * 
+ * + * @param str the String containing the substring, may be null + * @param open the String before the substring, may be null + * @param close the String after the substring, may be null + * @return the substring, null if no match + */ + public static function substringBetween(str:String, open:String, close:String):String { + if (str == null || open == null || close == null) { + return null; + } + var start:int = str.indexOf(open); + + if (start != INDEX_NOT_FOUND) { + var end:int = str.indexOf(close, start + open.length); + + if (end != INDEX_NOT_FOUND) { + return str.substring(start + open.length, end); + } + } + return null; + } + + /** + *

Strips any of a set of characters from the start and end of a String. + * This is similar to #trim() but allows the characters + * to be stripped to be controlled.

+ * + *

A null input String returns null. + * An empty string("") input returns the empty string.

+ * + *
+		 * StringUtils.strip(null, *)          = null
+		 * StringUtils.strip("", *)            = ""
+		 * StringUtils.strip("abc", null)      = "abc"
+		 * StringUtils.strip("  abc", null)    = "abc"
+		 * StringUtils.strip("abc  ", null)    = "abc"
+		 * StringUtils.strip(" abc ", null)    = "abc"
+		 * StringUtils.strip("  abcyx", "xyz") = "  abc"
+		 * 
+ * + * @param str the String to remove characters from, may be null + * @param stripChars the characters to remove, null treated as whitespace + * @return the stripped String, null if null String input + */ + public static function strip(str:String, stripChars:String):String { + if (isEmpty(str)) { + return str; + } + return stripEnd(stripStart(str, stripChars), stripChars); + } + + /** + *

Strips any of a set of characters from the start of a String.

+ * + *

A null input String returns null. + * An empty string("") input returns the empty string.

+ * + *
+		 * StringUtils.stripStart(null, *)          = null
+		 * StringUtils.stripStart("", *)            = ""
+		 * StringUtils.stripStart("abc", "")        = "abc"
+		 * StringUtils.stripStart("abc", null)      = "abc"
+		 * StringUtils.stripStart("  abc", null)    = "abc"
+		 * StringUtils.stripStart("abc  ", null)    = "abc  "
+		 * StringUtils.stripStart(" abc ", null)    = "abc "
+		 * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
+		 * 
+ * + * @param str the String to remove characters from, may be null + * @param stripChars the characters to remove, null treated as whitespace + * @return the stripped String, null if null String input + */ + public static function stripStart(str:String, stripChars:String):String { + if (isEmpty(str)) { + return str; + } + var p:RegExp = new RegExp('^[' + (stripChars != null ? stripChars : ' ') + ']*', ''); + return str.replace(p, ''); + } + + /** + *

Strips any of a set of characters from the end of a String.

+ * + *

A null input String returns null. + * An empty string("") input returns the empty string.

+ * + *

If the stripChars String is null, whitespace is + * stripped.

+ * + *
+		 * StringUtils.stripEnd(null, *)          = null
+		 * StringUtils.stripEnd("", *)            = ""
+		 * StringUtils.stripEnd("abc", "")        = "abc"
+		 * StringUtils.stripEnd("abc", null)      = "abc"
+		 * StringUtils.stripEnd("  abc", null)    = "  abc"
+		 * StringUtils.stripEnd("abc  ", null)    = "abc"
+		 * StringUtils.stripEnd(" abc ", null)    = " abc"
+		 * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
+		 * 
+ * + * @param str the String to remove characters from, may be null + * @param stripChars the characters to remove, null treated as whitespace + * @return the stripped String, null if null String input + */ + public static function stripEnd(str:String, stripChars:String):String { + if (isEmpty(str)) { + return str; + } + var p:RegExp = new RegExp('[' + (stripChars != null ? stripChars : ' ') + ']*$', ''); + return str.replace(p, ''); + } + + /** + *

Abbreviates a String using ellipses. This will turn + * "Now is the time for all good men" into "...is the time for..."

+ * + *

Works like abbreviate(String, int), but allows you to specify + * a "left edge" offset. Note that this left edge is not necessarily going to + * be the leftmost character in the result, or the first character following the + * ellipses, but it will appear somewhere in the result. + * + *

In no case will it return a String of length greater than + * maxWidth.

+ * + *
+		 * StringUtils.abbreviate(null, *, *)                = null
+		 * StringUtils.abbreviate("", 0, 4)                  = ""
+		 * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
+		 * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
+		 * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
+		 * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
+		 * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
+		 * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
+		 * 
+ * + * @param str the String to check, may be null + * @param offset left edge of source String + * @param maxWidth maximum length of result String, must be at least 4 + * @return abbreviated String, null if null String input + * @throws IllegalArgumentException if the width is too small + */ + public static function abbreviate(str:String, offset:int, maxWidth:int):String { + if (str == null) { + return str; + } + + if (maxWidth < 4) { + throw new IllegalArgumentError("Minimum abbreviation width is 4"); + } + + if (str.length <= maxWidth) { + return str; + } + + if (offset > str.length) { + offset = str.length; + } + + if ((str.length - offset) < (maxWidth - 3)) { + offset = str.length - (maxWidth - 3); + } + + if (offset <= 4) { + return str.substring(0, maxWidth - 3) + "..."; + } + + if (maxWidth < 7) { + throw new IllegalArgumentError("Minimum abbreviation width with offset is 7"); + } + + if ((offset + (maxWidth - 3)) < str.length) { + return "..." + abbreviate(str.substring(offset), 0, maxWidth - 3); + } + return "..." + str.substring(str.length - (maxWidth - 3)); + } + + /** + *

Finds the n-th index within a String, handling null. + * This method uses String#indexOf(String).

+ * + *

A null String will return -1.

+ * + *
+		 * StringUtils.ordinalIndexOf(null, *, *)          = -1
+		 * StringUtils.ordinalIndexOf(*, null, *)          = -1
+		 * StringUtils.ordinalIndexOf("", "", *)           = 0
+		 * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
+		 * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
+		 * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
+		 * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
+		 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+		 * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+		 * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
+		 * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
+		 * 
+ * + * @param str the String to check, may be null + * @param searchStr the String to find, may be null + * @param ordinal the n-th searchStr to find + * @return the n-th index of the search String, + * -1(INDEX_NOT_FOUND) if no match or null string input + */ + public static function ordinalIndexOf(str:String, searchStr:String, ordinal:int):int { + if (str == null || searchStr == null || ordinal <= 0) { + return INDEX_NOT_FOUND; + } + + if (searchStr.length == 0) { + return 0; + } + var found:int = 0; + var index:int = INDEX_NOT_FOUND; + + do { + index = str.indexOf(searchStr, index + 1); + + if (index < 0) { + return index; + } + found++; + } while (found < ordinal); + return index; + } + + /** + *

Counts how many times the substring appears in the larger String.

+ * + *

A null or empty("") String input returns 0.

+ * + *
+		 * StringUtils.countMatches(null, *)       = 0
+		 * StringUtils.countMatches("", *)         = 0
+		 * StringUtils.countMatches("abba", null)  = 0
+		 * StringUtils.countMatches("abba", "")    = 0
+		 * StringUtils.countMatches("abba", "a")   = 2
+		 * StringUtils.countMatches("abba", "ab")  = 1
+		 * StringUtils.countMatches("abba", "xxx") = 0
+		 * 
+ * + * @param str the String to check, may be null + * @param sub the substring to count, may be null + * @return the number of occurrences, 0 if either String is null + */ + public static function countMatches(str:String, sub:String):int { + if (isEmpty(str) || isEmpty(sub)) { + return 0; + } + return str.match(new RegExp('(' + sub + ')', 'g')).length; + } + + /** + *

Checks if String contains a search String, handling null. + * + *

A null String will return false.

+ * + *
+		 * StringUtils.contains(null, *)     = false
+		 * StringUtils.contains(*, null)     = false
+		 * StringUtils.contains("", "")      = true
+		 * StringUtils.contains("abc", "")   = true
+		 * StringUtils.contains("abc", "a")  = true
+		 * StringUtils.contains("abc", "z")  = false
+		 * 
+ * + * @param str the String to check, may be null + * @param searchStr the String to find, may be null + * @return true if the String contains the search String, + * false if not or null string input + */ + public static function contains(str:String, searchStr:String):Boolean { + if (str == null || searchStr == null) { + return false; + } + return new RegExp('(' + searchStr + ')', 'g').test(str); + } + + /** + *

Checks that the String does not contain certain characters.

+ * + *

A null String will return true. + * A null invalid character array will return true. + * An empty String("") always returns true.

+ * + *
+		 * StringUtils.containsNone(null, *)       = true
+		 * StringUtils.containsNone(*, null)       = true
+		 * StringUtils.containsNone("", *)         = true
+		 * StringUtils.containsNone("ab", "")      = true
+		 * StringUtils.containsNone("abab", "xyz") = true
+		 * StringUtils.containsNone("ab1", "xyz")  = true
+		 * StringUtils.containsNone("abz", "xyz")  = false
+		 * 
+ * + * @param str the String to check, may be null + * @param invalidChars a String of invalid chars, may be null + * @return true if it contains none of the invalid chars, or is null + */ + public static function containsNone(str:String, invalidChars:String):Boolean { + if (isEmpty(str) || invalidChars == null) { + return true; + } + return new RegExp('^[^' + invalidChars + ']*$', '').test(str); + } + + /** + *

Checks if the String contains only certain characters.

+ * + *

A null String will return false. + * A null valid character String will return false. + * An empty String("") always returns true.

+ * + *
+		 * StringUtils.containsOnly(null, *)       = false
+		 * StringUtils.containsOnly(*, null)       = false
+		 * StringUtils.containsOnly("", *)         = true
+		 * StringUtils.containsOnly("ab", "")      = false
+		 * StringUtils.containsOnly("abab", "abc") = true
+		 * StringUtils.containsOnly("ab1", "abc")  = false
+		 * StringUtils.containsOnly("abz", "abc")  = false
+		 * 
+ * + * @param str the String to check, may be null + * @param validChars a String of valid chars, may be null + * @return true if it only contains valid chars and is non-null + */ + public static function containsOnly(str:String, validChars:String):Boolean { + if (str == null || isEmpty(validChars)) { + return false; + } + + if (str.length == 0) { + return true; + } + return new RegExp('^[' + validChars + ']*$', 'g').test(str); + } + + /** + *

Search a String to find the first index of any + * character in the given set of characters.

+ * + *

A null String will return -1. + * A null search string will return -1.

+ * + *
+		 * StringUtils.indexOfAny(null, *)            = -1
+		 * StringUtils.indexOfAny("", *)              = -1
+		 * StringUtils.indexOfAny(*, null)            = -1
+		 * StringUtils.indexOfAny(*, "")              = -1
+		 * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
+		 * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
+		 * StringUtils.indexOfAny("aba","z")          = -1
+		 * 
+ * + * @param str the String to check, may be null + * @param searchChars the chars to search for, may be null + * @return the index of any of the chars, -1 if no match or null input + */ + public static function indexOfAny(str:String, searchChars:String):int { + if (isEmpty(str) || isEmpty(searchChars)) { + return INDEX_NOT_FOUND; + } + return str.search(new RegExp('[' + searchChars + ']', '')); + } + + /** + *

Search a String to find the first index of any + * character not in the given set of characters.

+ * + *

A null String will return -1. + * A null search string will return -1.

+ * + *
+		 * StringUtils.indexOfAnyBut(null, *)            = -1
+		 * StringUtils.indexOfAnyBut("", *)              = -1
+		 * StringUtils.indexOfAnyBut(*, null)            = -1
+		 * StringUtils.indexOfAnyBut(*, "")              = -1
+		 * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
+		 * StringUtils.indexOfAnyBut("aba","ab")         = -1
+		 * 
+ * + * @param str the String to check, may be null + * @param searchChars the chars to search for, may be null + * @return the index of any of the chars, -1 if no match or null input + */ + public static function indexOfAnyBut(str:String, searchChars:String):int { + if (isEmpty(str) || isEmpty(searchChars)) { + return INDEX_NOT_FOUND; + } + return str.search(new RegExp('[^' + searchChars + ']', '')); + } + + /** + *

Compares two Strings, and returns the portion where they differ. + *(More precisely, return the remainder of the second String, + * starting from where it's different from the first.)

+ * + *

For example, + * difference("i am a machine", "i am a robot") -> "robot".

+ * + *
+		 * StringUtils.difference(null, null) = null
+		 * StringUtils.difference("", "") = ""
+		 * StringUtils.difference("", "abc") = "abc"
+		 * StringUtils.difference("abc", "") = ""
+		 * StringUtils.difference("abc", "abc") = ""
+		 * StringUtils.difference("ab", "abxyz") = "xyz"
+		 * StringUtils.difference("abcde", "abxyz") = "xyz"
+		 * StringUtils.difference("abcde", "xyz") = "xyz"
+		 * 
+ * + * @param str1 the first String, may be null + * @param str2 the second String, may be null + * @return the portion of str2 where it differs from str1; returns the + * empty String if they are equal + */ + public static function difference(str1:String, str2:String):String { + if (str1 == null) { + return str2; + } + + if (str2 == null) { + return str1; + } + var att:int = indexOfDifference(str1, str2); + + if (att == -1) { + return EMPTY; + } + return str2.substring(att); + } + + /** + *

Compares two Strings, and returns the index at which the + * Strings begin to differ.

+ * + *

For example, + * indexOfDifference("i am a machine", "i am a robot") -> 7

+ * + *
+		 * StringUtils.indexOfDifference(null, null) = -1
+		 * StringUtils.indexOfDifference("", "") = -1
+		 * StringUtils.indexOfDifference("", "abc") = 0
+		 * StringUtils.indexOfDifference("abc", "") = 0
+		 * StringUtils.indexOfDifference("abc", "abc") = -1
+		 * StringUtils.indexOfDifference("ab", "abxyz") = 2
+		 * StringUtils.indexOfDifference("abcde", "abxyz") = 2
+		 * StringUtils.indexOfDifference("abcde", "xyz") = 0
+		 * 
+ * + * @param str1 the first String, may be null + * @param str2 the second String, may be null + * @return the index where str2 and str1 begin to differ; -1 if they are equal + */ + public static function indexOfDifference(str1:String, str2:String):int { + if (str1 == str2) { + return INDEX_NOT_FOUND; + } + + if (isEmpty(str1) || isEmpty(str2)) { + return 0; + } + var charIndex:int; + + for (charIndex = 0; charIndex < str1.length && charIndex < str2.length; ++charIndex) { + if (str1.charAt(charIndex) != str2.charAt(charIndex)) { + break; + } + } + + if (charIndex < str2.length || charIndex < str1.length) { + return charIndex; + } + return INDEX_NOT_FOUND; + } + + /** + *

Compares two Strings, returning true if they are equal.

+ * + *

nulls are handled without exceptions. Two null + * references are considered to be equal. The comparison is case sensitive.

+ * + *
+		 * StringUtils.equals(null, null)   = true
+		 * StringUtils.equals(null, "abc")  = false
+		 * StringUtils.equals("abc", null)  = false
+		 * StringUtils.equals("abc", "abc") = true
+		 * StringUtils.equals("abc", "ABC") = false
+		 * 
+ * + * @param str1 the first String, may be null + * @param str2 the second String, may be null + * @return true if the Strings are equal, case sensitive, or + * both null + */ + public static function equals(str1:String, str2:String):Boolean { + return str1 === str2; + } + + /** + *

Compares two Strings, returning true if they are equal ignoring + * the case.

+ * + *

nulls are handled without exceptions. Two null + * references are considered equal. Comparison is case insensitive.

+ * + *
+		 * StringUtils.equalsIgnoreCase(null, null)   = true
+		 * StringUtils.equalsIgnoreCase(null, "abc")  = false
+		 * StringUtils.equalsIgnoreCase("abc", null)  = false
+		 * StringUtils.equalsIgnoreCase("abc", "abc") = true
+		 * StringUtils.equalsIgnoreCase("abc", "ABC") = true
+		 * 
+ * + * @param str1 the first String, may be null + * @param str2 the second String, may be null + * @return true if the Strings are equal, case insensitive, or + * both null + */ + public static function equalsIgnoreCase(str1:String, str2:String):Boolean { + if (str1 == null && str2 == null) { + return true; + } else if (str1 == null || str2 == null) { + return false; + } + return equals(str1.toLowerCase(), str2.toLowerCase()); + } + + /** + *

Checks if the String contains only unicode letters.

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isAlpha(null)   = false
+		 * StringUtils.isAlpha("")     = true
+		 * StringUtils.isAlpha("  ")   = false
+		 * StringUtils.isAlpha("abc")  = true
+		 * StringUtils.isAlpha("ab2c") = false
+		 * StringUtils.isAlpha("ab-c") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains letters, and is non-null + */ + public static function isAlpha(str:String):Boolean { + return testString(str, /^[a-zA-Z]*$/); + } + + /** + *

Checks if the String contains only unicode letters and + * space(' ').

+ * + *

null will return false + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isAlphaSpace(null)   = false
+		 * StringUtils.isAlphaSpace("")     = true
+		 * StringUtils.isAlphaSpace("  ")   = true
+		 * StringUtils.isAlphaSpace("abc")  = true
+		 * StringUtils.isAlphaSpace("ab c") = true
+		 * StringUtils.isAlphaSpace("ab2c") = false
+		 * StringUtils.isAlphaSpace("ab-c") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains letters and space, + * and is non-null + */ + public static function isAlphaSpace(str:String):Boolean { + return testString(str, /^[a-zA-Z\s]*$/); + } + + /** + *

Checks if the String contains only unicode letters or digits.

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isAlphanumeric(null)   = false
+		 * StringUtils.isAlphanumeric("")     = true
+		 * StringUtils.isAlphanumeric("  ")   = false
+		 * StringUtils.isAlphanumeric("abc")  = true
+		 * StringUtils.isAlphanumeric("ab c") = false
+		 * StringUtils.isAlphanumeric("ab2c") = true
+		 * StringUtils.isAlphanumeric("ab-c") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains letters or digits, + * and is non-null + */ + public static function isAlphanumeric(str:String):Boolean { + return testString(str, /^[a-zA-Z0-9]*$/); + } + + /** + *

Checks if the String contains only unicode letters, digits + * or space(' ').

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isAlphanumericSpace(null)   = false
+		 * StringUtils.isAlphanumericSpace("")     = true
+		 * StringUtils.isAlphanumericSpace("  ")   = true
+		 * StringUtils.isAlphanumericSpace("abc")  = true
+		 * StringUtils.isAlphanumericSpace("ab c") = true
+		 * StringUtils.isAlphanumericSpace("ab2c") = true
+		 * StringUtils.isAlphanumericSpace("ab-c") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains letters, digits or space, + * and is non-null + */ + public static function isAlphanumericSpace(str:String):Boolean { + return testString(str, /^[a-zA-Z0-9\s]*$/); + } + + /** + *

Checks if the String contains only unicode digits. + * A decimal point is not a unicode digit and returns false.

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isNumeric(null)   = false
+		 * StringUtils.isNumeric("")     = true
+		 * StringUtils.isNumeric("  ")   = false
+		 * StringUtils.isNumeric("123")  = true
+		 * StringUtils.isNumeric("12 3") = false
+		 * StringUtils.isNumeric("ab2c") = false
+		 * StringUtils.isNumeric("12-3") = false
+		 * StringUtils.isNumeric("12.3") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains digits, and is non-null + */ + public static function isNumeric(str:String):Boolean { + return testString(str, /^[0-9]*$/); + } + + /** + *

Checks if the String contains only unicode digits or space + *(' '). + * A decimal point is not a unicode digit and returns false.

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isNumericSpace(null)   = false
+		 * StringUtils.isNumericSpace("")     = true
+		 * StringUtils.isNumericSpace("  ")   = true
+		 * StringUtils.isNumericSpace("123")  = true
+		 * StringUtils.isNumericSpace("12 3") = true
+		 * StringUtils.isNumericSpace("ab2c") = false
+		 * StringUtils.isNumericSpace("12-3") = false
+		 * StringUtils.isNumericSpace("12.3") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains digits or space, + * and is non-null + */ + public static function isNumericSpace(str:String):Boolean { + return testString(str, /^[0-9\s]*$/); + } + + /** + *

Checks if the String contains only whitespace.

+ * + *

null will return false. + * An empty String("") will return true.

+ * + *
+		 * StringUtils.isWhitespace(null)   = false
+		 * StringUtils.isWhitespace("")     = true
+		 * StringUtils.isWhitespace("  ")   = true
+		 * StringUtils.isWhitespace("abc")  = false
+		 * StringUtils.isWhitespace("ab2c") = false
+		 * StringUtils.isWhitespace("ab-c") = false
+		 * 
+ * + * @param str the String to check, may be null + * @return true if only contains whitespace, and is non-null + */ + public static function isWhitespace(str:String):Boolean { + return testString(str, /^[\s]*$/); + } + + private static function testString(str:String, pattern:RegExp):Boolean { + return str != null && pattern.test(str); + } + + /** + *

Overlays part of a String with another String.

+ * + *

A null string input returns null. + * A negative index is treated as zero. + * An index greater than the string length is treated as the string length. + * The start index is always the smaller of the two indices.

+ * + *
+		 * StringUtils.overlay(null, *, *, *)            = null
+		 * StringUtils.overlay("", "abc", 0, 0)          = "abc"
+		 * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
+		 * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
+		 * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
+		 * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
+		 * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
+		 * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
+		 * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
+		 * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
+		 * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
+		 * 
+ * + * @param str the String to do overlaying in, may be null + * @param overlay the String to overlay, may be null + * @param start the position to start overlaying at + * @param end the position to stop overlaying before + * @return overlayed String, null if null String input + */ + public static function overlay(str:String, overlay:String, start:int, end:int):String { + if (str == null) { + return null; + } + + if (overlay == null) { + overlay = EMPTY; + } + var len:int = str.length; + + if (start < 0) { + start = 0; + } + + if (start > len) { + start = len; + } + + if (end < 0) { + end = 0; + } + + if (end > len) { + end = len; + } + + if (start > end) { + var temp:int = start; // NO PMD WronglyNamedVariable + start = end; + end = temp; + } + return str.substring(0, start).concat(overlay).concat(str.substring(end)); + } + + /** + *

Removes all occurances of a substring from within the source string.

+ * + *

A null source string will return null. + * An empty("") source string will return the empty string. + * A null remove string will return the source string. + * An empty("") remove string will return the source string.

+ * + *
+		 * StringUtils.remove(null, *)        = null
+		 * StringUtils.remove("", *)          = ""
+		 * StringUtils.remove(*, null)        = *
+		 * StringUtils.remove(*, "")          = *
+		 * StringUtils.remove("queued", "ue") = "qd"
+		 * StringUtils.remove("queued", "zz") = "queued"
+		 * 
+ * + * @param str the source String to search, may be null + * @param remove the String to search for and remove, may be null + * @return the substring with the string removed if found, + * null if null String input + */ + public static function remove(str:String, remove:String):String { + return safeRemove(str, new RegExp(remove, 'g')); + } + + /** + *

Removes a substring only if it is at the end of a source string, + * otherwise returns the source string.

+ * + *

A null source string will return null. + * An empty("") source string will return the empty string. + * A null search string will return the source string.

+ * + *
+		 * StringUtils.removeEnd(null, *)      = null
+		 * StringUtils.removeEnd("", *)        = ""
+		 * StringUtils.removeEnd(*, null)      = *
+		 * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
+		 * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
+		 * StringUtils.removeEnd("abc", "")    = "abc"
+		 * 
+ * + * @param str the source String to search, may be null + * @param remove the String to search for and remove, may be null + * @return the substring with the string removed if found, + * null if null String input + */ + public static function removeEnd(str:String, remove:String):String { + return safeRemove(str, new RegExp(remove + '$', '')); + } + + /** + *

Removes a substring only if it is at the begining of a source string, + * otherwise returns the source string.

+ * + *

A null source string will return null. + * An empty("") source string will return the empty string. + * A null search string will return the source string.

+ * + *
+		 * StringUtils.removeStart(null, *)      = null
+		 * StringUtils.removeStart("", *)        = ""
+		 * StringUtils.removeStart(*, null)      = *
+		 * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
+		 * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
+		 * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
+		 * StringUtils.removeStart("abc", "")    = "abc"
+		 * 
+ * + * @param str the source String to search, may be null + * @param remove the String to search for and remove, may be null + * @return the substring with the string removed if found, + * null if null String input + */ + public static function removeStart(str:String, remove:String):String { + return safeRemove(str, new RegExp('^' + remove, '')); + } + + private static function safeRemove(str:String, pattern:RegExp):String { + if (isEmpty(str)) { + return str; + } + return str.replace(pattern, ''); + } + + /** + *

Checks if the String end characters match the given end string.

+ * + *

null will return false. + * + *

+		 * StringUtils.endsWith(null, *)	 				= false
+		 * StringUtils.endsWith(null, null) 				= false
+		 * StringUtils.endsWith(*, null)	   				= false
+		 * StringUtils.endsWith("www.domain.com", "com") = true
+		 * 
+ * + * @param str the String to check, may be null + * @param end the string to compare + * @return true if only contains whitespace, and is non-null + */ + public static function endsWith(str:String, end:String):Boolean { + return testString(str, new RegExp(end + '$', '')); + } + + /** + *

Checks if the String start characters match the given start string.

+ * + *

null will return false. + * + *

+		 * StringUtils.startsWith(null, *)	 				= false
+		 * StringUtils.startsWith(null, null) 				= false
+		 * StringUtils.startsWith(*, null)	   				= false
+		 * StringUtils.startsWith("www.domain.com", "www.")	= true
+		 * 
+ * + * @param str the String to check, may be null + * @param start the string to compare + * @return true if only contains whitespace, and is non-null + */ + public static function startsWith(str:String, start:String):Boolean { + return testString(str, new RegExp('^' + start, '')); + } + + /** + * Compares two strings lexicographically, ignoring case + * differences. This method returns an integer whose sign is that of + * calling compareTo with normalized versions of the strings + * where case differences have been eliminated by calling + * Character.toLowerCase(Character.toUpperCase(character)) on + * each character. + *

+ * + * @param str1 the String to be compared. + * @param str2 the String to be compared. + * @return a negative integer, zero, or a positive integer as the + * specified String is greater than, equal to, or less + * than this String, ignoring case considerations. + */ + public static function compareToIgnoreCase(str1:String, str2:String):int { + if (str1 == null) { + str1 = ""; + } + + if (str2 == null) { + str2 = ""; + } + + return compareTo(str1.toLowerCase(), str2.toLowerCase()); + } + + /** + * Compares two strings lexicographically. + * The comparison is based on the Unicode value of each character in + * the strings. The character sequence represented by this + * String object is compared lexicographically to the + * character sequence represented by the argument string. The result is + * a negative integer if this String object + * lexicographically precedes the argument string. The result is a + * positive integer if this String object lexicographically + * follows the argument string. The result is zero if the strings + * are equal; compareTo returns 0 exactly when + * the #equals(Object) method would return true. + *

+ * This is the definition of lexicographic ordering. If two strings are + * different, then either they have different characters at some index + * that is a valid index for both strings, or their lengths are different, + * or both. If they have different characters at one or more index + * positions, let k be the smallest such index; then the string + * whose character at position k has the smaller value, as + * determined by using the < operator, lexicographically precedes the + * other string. In this case, compareTo returns the + * difference of the two character values at position k in + * the two string -- that is, the value: + *

+		 * this.charAt(k)-anotherString.charAt(k)
+		 * 
+ * If there is no index position at which they differ, then the shorter + * string lexicographically precedes the longer string. In this case, + * compareTo returns the difference of the lengths of the + * strings -- that is, the value: + *
+		 * this.length-anotherString.length
+		 * 
+ * + * @param anotherString the String to be compared. + * @return the value 0 if the argument string is equal to + * this string; a value less than 0 if this string + * is lexicographically less than the string argument; and a + * value greater than 0 if this string is + * lexicographically greater than the string argument. + */ + public static function compareTo(str1:String, str2:String):int { + if (str1 == null) { + str1 = ""; + } + + if (str2 == null) { + str2 = ""; + } + return str1.localeCompare(str2); + } + + /** + * Adds/inserts a new string at a certain position in the source string. + */ + public static function addAt(string:String, value:*, position:int):String { + if (position > string.length) { + position = string.length; + } + var firstPart:String = string.substring(0, position); + var secondPart:String = string.substring(position, string.length); + return (firstPart + value + secondPart); + } + + /** + * Replaces a part of the text between 2 positions. + */ + public static function replaceAt(string:String, value:*, beginIndex:int, endIndex:int):String { + beginIndex = Math.max(beginIndex, 0); + endIndex = Math.min(endIndex, string.length); + var firstPart:String = string.substr(0, beginIndex); + var secondPart:String = string.substr(endIndex, string.length); + return (firstPart + value + secondPart); + } + + /** + * Removes a part of the text between 2 positions. + */ + public static function removeAt(string:String, beginIndex:int, endIndex:int):String { + return StringUtils.replaceAt(string, "", beginIndex, endIndex); + } + + /** + * Fixes double newlines in a text. + */ + public static function fixNewlines(string:String):String { + return string.replace(/\r\n/gm, "\n"); + } + + /** + * Checks if the given string has actual text. + */ + public static function hasText(string:String):Boolean { + if (!string) + return false; + return (StringUtils.trim(string).length > 0); + } + + /** + * Removes all empty characters at the beginning of a string. + * + *

Characters that are removed: spaces {@code " "}, line forwards {@code "\n"} + * and extended line forwarding {@code "\t\n"}. + * + * @param string the string to trim + * @return the trimmed string + */ + public static function leftTrim(string:String):String { + return leftTrimForChars(string, "\n\t\n "); + } + + /** + * Removes all empty characters at the end of a string. + * + *

Characters that are removed: spaces {@code " "}, line forwards {@code "\n"} + * and extended line forwarding {@code "\t\n"}. + * + * @param string the string to trim + * @return the trimmed string + */ + public static function rightTrim(string:String):String { + return rightTrimForChars(string, "\n\t\n "); + } + + /** + * Removes all characters at the beginning of the {@code string} that match to the + * set of {@code chars}. + * + *

This method splits all {@code chars} and removes occurencies at the beginning. + * + *

Example: + * + * trace(StringUtil.rightTrimForChars("ymoynkeym", "ym")); // oynkeym + * trace(StringUtil.rightTrimForChars("monkey", "mo")); // nkey + * trace(StringUtil.rightTrimForChars("monkey", "om")); // nkey + * + * + * @param string the string to trim + * @param chars the characters to remove from the beginning of the {@code string} + * @return the trimmed string + */ + public static function leftTrimForChars(string:String, chars:String):String { + var from:Number = 0; + var endIndex:Number = string.length; + + while (from < endIndex && chars.indexOf(string.charAt(from)) >= 0) { + from++; + } + return (from > 0 ? string.substr(from, endIndex) : string); + } + + /** + * Removes all characters at the end of the {@code string} that match to the set of + * {@code chars}. + * + *

This method splits all {@code chars} and removes occurencies at the end. + * + *

Example: + * + * trace(StringUtil.rightTrimForChars("ymoynkeym", "ym")); // ymoynke + * trace(StringUtil.rightTrimForChars("monkey***", "*y")); // monke + * trace(StringUtil.rightTrimForChars("monke*y**", "*y")); // monke + * + * + * @param string the string to trim + * @param chars the characters to remove from the end of the {@code string} + * @return the trimmed string + */ + public static function rightTrimForChars(string:String, chars:String):String { + var from:Number = 0; + var endIndex:Number = string.length - 1; + + while (from < endIndex && chars.indexOf(string.charAt(endIndex)) >= 0) { + endIndex--; + } + return (endIndex >= 0 ? string.substr(from, endIndex + 1) : string); + } + + /** + * Removes all characters at the beginning of the {@code string} that matches the + * {@code char}. + * + *

Example: + * + * trace(StringUtil.leftTrimForChar("yyyymonkeyyyy", "y"); // monkeyyyy + * + * + * @param string the string to trim + * @param char the character to remove + * @return the trimmed string + * @throws IllegalArgumentException if you try to remove more than one character + */ + public static function leftTrimForChar(string:String, char:String):String { + if (char.length != 1) { + throw new IllegalArgumentError("The Second Attribute char [" + char + "] must exactly one character."); + } + return leftTrimForChars(string, char); + } + + /** + * Removes all characters at the end of the {@code string} that matches the passed-in + * {@code char}. + * + *

Example: + * + * trace(StringUtil.rightTrimForChar("yyyymonkeyyyy", "y"); // yyyymonke + * + * + * @param string the string to trim + * @param char the character to remove + * @return the trimmed string + * @throws IllegalArgumentException if you try to remove more than one character + */ + public static function rightTrimForChar(string:String, char:String):String { + if (char.length != 1) { + throw new IllegalArgumentError("The Second Attribute char [" + char + "] must exactly one character."); + } + return rightTrimForChars(string, char); + } + + /** + * Extended String::indexOf + * + * @param haystack string to search in + * @param n which ocurance of needle + * @param needle The substring for which to search + * @param startIndex An optional integer specifying the starting index of the search. + * @returns startIndex if n is 0 + * @returns -1 if not enough ocurances of needle are found + * @returns charIndex of nth needle ocurances + */ + public static function nthIndexOf(haystack:String, n:uint, needle:String, startIndex:Number = 0):int { + var result:int = startIndex; + + if (n >= 1) { + result = haystack.indexOf(needle, result); + + for (var i:int = 1; result != -1 && i < n; i++) { + result = haystack.indexOf(needle, result + 1); + } + } + return result; + } + + /** + * Returns if the given character is a white space or not. + */ + public static function characterIsWhitespace(a:String):Boolean { + return (a.charCodeAt(0) <= 32); + } + + /** + * Returns if the given character is a digit or not. + */ + public static function characterIsDigit(a:String):Boolean { + var charCode:Number = a.charCodeAt(0); + return (charCode >= 48 && charCode <= 57); + } + + /** + * Natural sort order compare function. + * + * @ignore Based on the JavaScript version by Kristof Coomans. + * (http://sourcefrog.net/projects/natsort/natcompare.js) + */ + public static function naturalCompare(a:String, b:String):int { // NO PMD TooLongFunction + var iaa:int = 0, ibb:int = 0; + var nza:int = 0, nzb:int = 0; + var caa:String, cbb:String; + var result:int; + var lowerCaseBeforeUpperCase:Boolean = true; // used to be a method argument, keep this + + // replace null values with empty strings + if (!a) + a = ""; + + if (!b) + b = ""; + + /*if (!caseSensitive) { + a = a.toLowerCase(); + b = b.toLowerCase(); + }*/ + + var stringsAreCaseInsensitiveEqual:Boolean = false; + + if (a.toLocaleLowerCase() == b.toLocaleLowerCase()) { + stringsAreCaseInsensitiveEqual = true; + } else { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + + while (true) { + // only count the number of zeroes leading the last number compared + nza = nzb = 0; + + caa = a.charAt(iaa); + cbb = b.charAt(ibb); + + // skip over leading spaces or zeros + while (StringUtils.characterIsWhitespace(caa) || caa == "0") { + if (caa == "0") { + nza++; + } else { + // only count consecutive zeroes + nza = 0; + } + + caa = a.charAt(++iaa); + } + + while (StringUtils.characterIsWhitespace(cbb) || cbb == "0") { + if (cbb == "0") { + nzb++; + } else { + // only count consecutive zeroes + nzb = 0; + } + + cbb = b.charAt(++ibb); + } + + // process run of digits + if (StringUtils.characterIsDigit(caa) && StringUtils.characterIsDigit(cbb)) { + if ((result = compareRight(a.substring(iaa), b.substring(ibb))) != 0) { + return result; + } + } + + if (caa == "" && cbb == "") { + // The strings compare the same. Perhaps the caller + // will want to call strcmp to break the tie. + return nza - nzb; + } + + if (stringsAreCaseInsensitiveEqual) { + // If the characters are in another case (upper or lower) + if (caa != cbb) { + if (caa < cbb) { // NO PMD DeeplyNestedIf + return lowerCaseBeforeUpperCase ? +1 : -1; + } else if (caa > cbb) { + return lowerCaseBeforeUpperCase ? -1 : +1; + } + } + } + + if (caa < cbb) { + return -1; + } else if (caa > cbb) { + return +1; + } + + ++iaa; + ++ibb; + } + + return 0; + } + + /** + * Helper function used by the naturalCompare method. + */ + private static function compareRight(a:String, b:String):int { + var bias:int = 0; + var iaa:int = 0; + var ibb:int = 0; + var caa:String; + var cbb:String; + + // The longest run of digits wins. That aside, the greatest + // value wins, but we can't know that it will until we've scanned + // both numbers to know that they have the same magnitude, so we + // remember it in BIAS. + for (; ; iaa++, ibb++) { + caa = a.charAt(iaa); + cbb = b.charAt(ibb); + + if (!StringUtils.characterIsDigit(caa) && !StringUtils.characterIsDigit(cbb)) { + return bias; + } else if (!StringUtils.characterIsDigit(caa)) { + return -1; + } else if (!StringUtils.characterIsDigit(cbb)) { + return +1; + } else if (caa < cbb) { + if (bias == 0) { + bias = -1; + } + } else if (caa > cbb) { + if (bias == 0) + bias = +1; + } else if (caa == "" && cbb == "") { + return bias; + } + } + + return 0; + } + + /** + * Tokenizes a string to an array using the given delimiters. + */ + public static function tokenizeToArray(string:String, delimiters:String):Array { + var result:Array = []; + var numCharacters:int = string.length; + var delimiterFound:Boolean = false; // NO PMD UnusedLocalVariable + var token:String = ""; + + for (var i:int = 0; i < numCharacters; i++) { + var character:String = string.charAt(i); + + if (delimiters.indexOf(character) == -1) { + token += character; + } else { + result.push(token); + token = ""; + } + + // add the last token if we reached the end of the string + if (i == numCharacters - 1) { + result.push(token); + } + } + + return result; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/ff722d6f/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD232.as ---------------------------------------------------------------------- diff --git a/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD232.as b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD232.as new file mode 100644 index 0000000..571c278 --- /dev/null +++ b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD232.as @@ -0,0 +1,36 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// +package src.live ; +{ + class LiveRecording13 + { + public function recordNoCheckTimeShifting(program:EpgProgramShort, epgDay:EpgDay, channelNumber:Number):Void + { + if (channelNumber != Zapping.getInstance().getCurrentLCN() && + ( (aPossibilities.length == 0) + || /* Shouldn't be necessery to test because of getTheBestPossibleUriToRecord() */ + !EligibigityConflictController.getInstance().canRecordWhileDisplaying(uriToRecord, videoDefToRecord) + ) + ) + { + return ; + } + } + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/ff722d6f/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD233a.mxml ---------------------------------------------------------------------- diff --git a/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD233a.mxml b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD233a.mxml new file mode 100644 index 0000000..58026d1 --- /dev/null +++ b/FlexPMD/language-module/ruleset/ruleset-flex-basic/src/test/resources/test/bug/FlexPMD233a.mxml @@ -0,0 +1,91 @@ + + + + + + [HostComponent("spark.components.SkinnableContainer")] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +