Java tutorial
/* * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved. * * Project: OpenSubsystems * * $Id: StringUtils.java,v 1.14 2007/02/20 04:08:10 bastafidli Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; /** * Utility methods for String manipulation. * * @version $Id: StringUtils.java,v 1.14 2007/02/20 04:08:10 bastafidli Exp $ * @author Peter Satury * @code.reviewer Miro Halas * @code.reviewed 1.11 2006/04/29 00:24:18 jlegeny */ public final class StringUtils { // Constants //////////////////////////////////////////////////////////////// /** * Constant for assigning */ public static final String EMPTY_STRING = ""; /** * Constant for assigning */ public static final String COMMA_STRING = ","; /** * Keep the original case of the string; */ public static final int CASE_ORIGINAL = 0; /** * Convert the string to upper case. */ public static final int CASE_TOUPPER = 1; /** * Convert the string to lower case. */ public static final int CASE_TOLOWER = 2; // Constructors ///////////////////////////////////////////////////////////// /** * Private constructor since this class cannot be instantiated */ private StringUtils() { // Do nothing } // Public methods /////////////////////////////////////////////////////////// /** * Count number of occurences of lookup in text. * * @param text - * text to search in for occurences of lookup * @param lookup - * character to count * @return int - number of occurences of lookup in text. */ public static int count(String text, char lookup) { int iCount = 0; if (text != null) { int iIndex = text.indexOf(lookup); while (iIndex != -1) { iCount++; iIndex = text.indexOf(lookup, iIndex + 1); } } return iCount; } /** * Parse textual representation of fraction to a floating point number * * @param textToParse - * in the form "any_text whole_part quotient/divisor any_text" * @param defaultValue - * if the test is unparsable, what default value to return * @param bIgnoreRest - * if true, this will ignore the rest of the string (any_other_text) * after the fraction, if false then the whole string is considered * @return double - number coresponding to the fraction */ public static double parseFraction(String textToParse, double defaultValue, boolean bIgnoreRest) { double parsed = defaultValue; int iLength; int iIndex; int iIndexStart; int iIndexEnd; int iNumber; // lets use "xxxxxxx 123 456 / 789 yyyyy" as example or // lets use "xxxxxxx 123 / 789 yyyyy" as example iIndexStart = 0; iLength = textToParse.length(); if (bIgnoreRest) { // Skip while not number while ((iIndexStart < iLength) && (!Character.isDigit(textToParse.charAt(iIndexStart)))) { iIndexStart++; } // We skiped "xxxxxxx", iIndexStart is at "123 456 / 789 yyyyy" } // We should be at first digit if (iIndexStart < iLength) { // Find end of the number iIndex = iIndexStart; while ((iIndex < iLength) && (Character.isDigit(textToParse.charAt(iIndex)))) { iIndex++; } iIndexEnd = iIndex; // We skiped "123", iIndexStart is at "123 456 / 789 yyyyy" // iIndexEnd is at " 456 / 789 yyyyy" if (iIndexStart != iIndexEnd) { // There was at least some digits iNumber = Integer.parseInt(textToParse.substring(iIndexStart, iIndexEnd)); // iNumber is 123 // There was at least one digit, now is it whole part or quotient? // Skip spaces while ((iIndex < iLength) && ((textToParse.charAt(iIndex) == ' ') || (textToParse.charAt(iIndex) == '-'))) { iIndex++; } // We skiped "123", iIndex is at "456 / 789 yyyyy" // Now we have stopped because of 2 things, we either reached end of // string or we have found something other than space, if it is / // then it was qoutient, if it is digit, then it was whole part if (iIndex == iLength) { // it was a whole part and we are done parsed = iNumber; } else { int iQuotient = 0; int iDivisor = Integer.MAX_VALUE; if (Character.isDigit(textToParse.charAt(iIndex))) { int iWholePart = 0; // it was a whole part and we continue to look for the quotient iWholePart = iNumber; // Find end of the number iIndexStart = iIndex; // Remember start while ((iIndex < iLength) && (Character.isDigit(textToParse.charAt(iIndex)))) { iIndex++; } iIndexEnd = iIndex; // We skiped "456", iStartIndex is at "456 / 789 yyyyy" // And iIndexEnd is at " / 789 yyyyy" iQuotient = Integer.parseInt(textToParse.substring(iIndexStart, iIndexEnd)); // iQuotient is 456 // Skip spaces while ((iIndex < iLength) && (textToParse.charAt(iIndex) == ' ')) { iIndex++; } // And iIndex is at "/ 789 yyyyy" if (textToParse.charAt(iIndex) == '/') { // It was a quotient and we continue to look for divisor iIndexStart = iIndex + 1; while ((iIndexStart < iLength) && (textToParse.charAt(iIndexStart) == ' ')) { iIndexStart++; } // And iIndexStart is at "789 yyyyy" // We should be at next digit if (iIndexStart < iLength) { // Find end of the number iIndex = iIndexStart; while ((iIndex < iLength) && (Character.isDigit(textToParse.charAt(iIndex)))) { iIndex++; } iIndexEnd = iIndex; // We skiped "789", iStartIndex is at "789 yyyyy" // And iIndexEnd is at " yyyyy" if (iIndexStart != iIndexEnd) { iDivisor = Integer.parseInt(textToParse.substring(iIndexStart, iIndexEnd)); // iDivisor is 789 if (iDivisor != 0) { if (iIndexEnd == iLength) { // And we are at the end of the string parsed = ((double) (iWholePart)) + (((double) iQuotient) / ((double) iDivisor)); } else { if (bIgnoreRest) { // And we can ignore what is after parsed = ((double) (iWholePart)) + (((double) iQuotient) / ((double) iDivisor)); } else { // there was something else we don't know what so // return the default value } } } } else { // The divisor is missing, return default value } } else { // The divisor is missing, return default value } } else { // The divisor is missing, return default value } } else { if (textToParse.charAt(iIndex) == '/') { // And iIndex is at "/ 456 yyyyy" // It was a quotient and we continue to look for divisor iQuotient = iNumber; // iQuotient is 123 iIndexStart = iIndex + 1; while ((iIndexStart < iLength) && (textToParse.charAt(iIndexStart) == ' ')) { iIndexStart++; } // And iIndexStart is at "456 yyyyy" // We should be at next digit if (iIndexStart < iLength) { // Find end of the number iIndex = iIndexStart; while ((iIndex < iLength) && (Character.isDigit(textToParse.charAt(iIndex)))) { iIndex++; } iIndexEnd = iIndex; // We skipped "456", iIndexStart is at "456 yyyyy" // iIndexEnd is at " yyyyy" if (iIndexStart != iIndexEnd) { iDivisor = Integer.parseInt(textToParse.substring(iIndexStart, iIndexEnd)); // iDivisor is 456 if (iDivisor != 0) { if (iIndexEnd == iLength) { // And we are at the end of the string parsed = ((double) iQuotient) / ((double) iDivisor); } else { if (bIgnoreRest) { // And we can ignore what is after parsed = ((double) iQuotient) / ((double) iDivisor); } else { // there was something else we don't know what so // return the default value } } } } else { // The divisor is missing, return default value } } else { // The divisor is missing, return default value } } else { // It was a whole part and there is something else if (bIgnoreRest) { // and we are done parsed = iNumber; } else { // there was something else we don't know what so // return the default value } } } } } } return parsed; } /** * Parse String to array of Strings while treating quoted values as single * element. * * @param strParse - * String to parse * @param strDel - * String deliminer * @param bAllowSingleQuote - * single qoutes such as ' can be used to group value * @param bAllowDoubleQuote - * double quote such as " can be used to group value * @return String[] - parsed list * @throws OSSInvalidDataException - * error during parsing */ public static String[] parseQuotedStringToStringArray(String strParse, String strDel, boolean bAllowSingleQuote, boolean bAllowDoubleQuote) throws Exception { String[] arrayStrings; if (strParse == null) { arrayStrings = null; } else { List lstElements = new ArrayList(); int iCurrentIndex = 0; int iNextIndex; int iDelLength = strDel.length(); int iParseLength = strParse.length(); while (iCurrentIndex < iParseLength) { if ((bAllowSingleQuote) && (strParse.charAt(iCurrentIndex) == '\'')) { // Find next single quote and treat the things in the middle as // single element iNextIndex = strParse.indexOf('\'', iCurrentIndex + 1); if (iNextIndex == -1) { throw new Exception("Incorrect input. " + strParse + " No single quote following the one" + " at location " + iCurrentIndex); } lstElements.add(strParse.substring(iCurrentIndex + 1, iNextIndex)); iCurrentIndex = iNextIndex + 1; if (strParse.substring(iCurrentIndex).startsWith(strDel)) { iCurrentIndex += iDelLength; } } else if ((bAllowDoubleQuote) && (strParse.charAt(iCurrentIndex) == '"')) { // Find next double quote and treat the things in the middle as // single element iNextIndex = strParse.indexOf('"', iCurrentIndex + 1); if (iNextIndex == -1) { throw new Exception("Incorrect input. " + strParse + " No double quote following the one" + " at location " + iCurrentIndex); } lstElements.add(strParse.substring(iCurrentIndex + 1, iNextIndex)); iCurrentIndex = iNextIndex + 1; if (strParse.substring(iCurrentIndex).startsWith(strDel)) { iCurrentIndex += iDelLength; } } else { // Find next separator and treat the things in the middle as // single element iNextIndex = strParse.indexOf(strDel, iCurrentIndex); if (iNextIndex == -1) { // No other delimiter found so take the rest of the string lstElements.add(strParse.substring(iCurrentIndex)); iCurrentIndex = iParseLength; } else { lstElements.add(strParse.substring(iCurrentIndex, iNextIndex)); iCurrentIndex = iNextIndex + iDelLength; } } } arrayStrings = (String[]) lstElements.toArray(new String[lstElements.size()]); } return arrayStrings; } /** * Parse String to array of integers. * * @param strParse - * String to parse * @param strDel - * String deliminer * @return int[] - parsed list * @throws OSSException - * error during parsing */ public static int[] parseStringToIntArray(String strParse, String strDel) throws Exception { int[] arrayInts; try { if (strParse == null) { arrayInts = null; } else { // TODO: Performance: Memory vs speed, here we allocate list and then // another array, how about just counting the number of elements // and then allocating array and parsing directly to array without // the extra list and copying from list to array? List lstInts = parseStringToList(strParse, strDel); if (lstInts == null || lstInts.size() < 1) { arrayInts = null; } else { Iterator items; int iCount; arrayInts = new int[lstInts.size()]; for (iCount = 0, items = lstInts.iterator(); items.hasNext();) { arrayInts[iCount++] = Integer.parseInt(((String) items.next()).trim()); } } } } catch (NumberFormatException eExc) { throw new RuntimeException("Problems with parsing String to array of int.", eExc); } return arrayInts; } /** * Parse String to array of Integers. * * @param strParse - * String to parse * @param strDel - * String deliminer * @return Integer[] - parsed list * @throws OSSException - * error during parsing */ public static Integer[] parseStringToIntegerArray(String strParse, String strDel) throws Exception { Integer[] arrayInts; try { if (strParse == null) { arrayInts = null; } else { // TODO: Performance: Memory vs speed, here we allocate list and then // another array, how about just counting the number of elements // and then allocating array and parsing directly to array without // the extra list and copying from list to array? List strInts = parseStringToList(strParse, strDel); if (strInts == null || strInts.size() < 1) { arrayInts = null; } else { arrayInts = new Integer[strInts.size()]; for (int iCount = 0; iCount < strInts.size(); iCount++) { arrayInts[iCount] = Integer.valueOf((String) strInts.get(iCount)); } } } } catch (NumberFormatException eExc) { throw new RuntimeException("Problems with parsing String to array of int.", eExc); } return arrayInts; } /** * Parse String to array of Strings. * * @param strParse - * String to parse * @param strDel - * String deliminer * @return String[] - parsed list */ public static String[] parseStringToStringArray(String strParse, String strDel) { String[] arrayStrings; if (strParse == null) { arrayStrings = null; } else { // TODO: Performance: Memory vs speed, here we allocate list and then // another array, how about just counting the number of elements // and then allocating array and parsing directly to array without // the extra list and copying from list to array? List lstStrings = parseStringToList(strParse, strDel); if ((lstStrings == null) || (lstStrings.isEmpty())) { arrayStrings = null; } else { arrayStrings = (String[]) lstStrings.toArray(new String[lstStrings.size()]); } } return arrayStrings; } /** * Parse array of integers to String. * * @param arrParse - * int array to parse * @param strDel - * String deliminer * @return String - parsed array */ public static String parseIntArrayToString(int[] arrParse, String strDel) { StringBuffer strbInts = new StringBuffer(); if ((arrParse != null) && (arrParse.length > 0)) { for (int iCount = 0; iCount < arrParse.length; iCount++) { if (iCount > 0) { strbInts.append(strDel); } strbInts.append(arrParse[iCount]); } } return strbInts.toString(); } /** * Parse collection of objects to String by calling toString on each element. * * @param colObjects - * collection of data objects to parse * @param strDel - * String deliminer * @return String - parsed array */ public static String parseCollectionToString(Collection colObjects, String strDel) { StringBuffer strbInts = new StringBuffer(); if ((colObjects != null) && (!colObjects.isEmpty())) { for (Iterator items = colObjects.iterator(); items.hasNext();) { if (strbInts.length() > 0) { strbInts.append(strDel); } strbInts.append(items.next().toString()); } } return strbInts.toString(); } /** * Parse String to List. * * @param strParse - * String to parse * @param strDel - * String deliminer * @return List - parsed list of items in the string delimtied by delimiter */ public static List parseStringToList(String strParse, String strDel) { return (List) parseStringToCollection(strParse, strDel, false, CASE_ORIGINAL, null); } /** * Parse String to ANY collection you specify and trim each item. * * @param strParse - * String to parse * @param strDel - * String deliminer * @param container - * if specified then it will be filled with items (it WILL NOT be * emptied first). If this is null, the default collection will be * allocated. This allows you here to pass list or set so this method * is more flexible. * @param bTrim - * should it be trimmed or not * @param iConvertCase - * how to convert the case of the string - one of the CASE_XXX * costants * @return Collection - parsed collection, if container was specified, the * same object will be returned. If it was not specified default * object will be returned. If strParse was not null, then this will * be not null. */ public static Collection parseStringToCollection(String strParse, String strDel, boolean bTrim, int iConvertCase, Collection container) { Collection colReturn; if (strParse == null || strParse.length() < 1) { if (container != null) { colReturn = container; } else { colReturn = null; } } else { // TODO: Performance: StringTokenizer is considered to be slow // because it creates lots of objects internally, consider replacing // this with String.indexOf(delimiter) StringTokenizer strTokParse = new StringTokenizer(strParse, strDel); String strTemp; if (container == null) { // This has to be List since parseStringToList requires it colReturn = new ArrayList(); } else { container.clear(); colReturn = container; } if (strParse.startsWith(strDel)) { // If the string starts with the delimiter, tokenizer would skip it // but we have to have empty element in front colReturn.add(""); } while (strTokParse.hasMoreTokens()) { strTemp = (String) strTokParse.nextToken(); if (bTrim) { strTemp = strTemp.trim(); } switch (iConvertCase) { case (CASE_ORIGINAL): { // do nothing break; } case (CASE_TOUPPER): { strTemp = strTemp.toUpperCase(); break; } case (CASE_TOLOWER): { strTemp = strTemp.toLowerCase(); break; } default: { assert false : "Incorrect case specification."; } } colReturn.add(strTemp); } } return colReturn; } /** * Method to limit String length for display and add '...' to the end * * @param limitLength - * limit of length * @param strValue - * String to limit * @return String - limited String */ public static String limitStringLength(int limitLength, String strValue) { StringBuffer sbReturn = new StringBuffer(); if ((limitLength > 0) && (strValue.length() > limitLength)) { // If limit length is lower then 5 we will do just exact substring if (limitLength < 5) { sbReturn.append(strValue.substring(0, limitLength)); } // If limit length is lower then 15 and higher then 4 we will // return substring of (limit - 3) and '...' else if (limitLength < 15) { sbReturn.append(strValue.substring(0, limitLength - 3)); sbReturn.append("..."); } // If limit length is higher then 15 we will try to find // some space ' ' near before limit and cut string there else { // if we will not find ' ' near before limit // we will return substring of (limit - 3) and '...' if ((strValue.indexOf(" ", limitLength - 12) > (limitLength - 4)) || (strValue.indexOf(" ", limitLength - 12) < 0)) { sbReturn.append(strValue.substring(0, limitLength - 3)); sbReturn.append("..."); } // if we will find ' ' near before limit // we will return substring until ' ' and ' ...' else { sbReturn.append(strValue.substring(0, strValue.indexOf(" ", limitLength - 12))); sbReturn.append(" ..."); } } } else { sbReturn.append(strValue); } return sbReturn.toString(); } /** * Method to remove comma from start and from end of the string for examples * to use it as parameter to SQL IN operator * * @param strToRemoveFrom - * String to remove comma from * @return String - string with removed commas from the start and end of the * string */ public static String removeComma(String strToRemoveFrom) { // we have to remove comma from start and from end of the string // because then it can be used for SQL IN operator if (strToRemoveFrom.length() > 2) { strToRemoveFrom = strToRemoveFrom.substring(1, strToRemoveFrom.length() - 1); } else { strToRemoveFrom = ""; } return strToRemoveFrom; } /** * Concat all the specified strings to a single one * * @param strings - * strings to concat, all null and empty ones will be ignored * @param separator - * separator to put in between the string elements * @param quote - * quote string to put around string elements, if null nothing will * be put around them * @return String with concatenated inputs */ public static String concat(String[] strings, String separator, String quote) { StringBuffer output = new StringBuffer(); if (strings != null) { int iIndex; boolean bSeparator; boolean bQuote; bSeparator = (separator != null) && (separator.length() > 0); bQuote = (quote != null) && (quote.length() > 0); for (iIndex = 0; iIndex < strings.length; iIndex++) { if ((strings[iIndex] != null) && (strings[iIndex].length() > 0)) { if ((output.length() > 0) && (bSeparator)) { output.append(separator); } if (bQuote) { output.append(quote); } output.append(strings[iIndex]); if (bQuote) { output.append(quote); } } } } return output.toString(); } /** * Test if any element in the container contains given string. * * @param container - * container of which elements will be searched to see if they * contains given text * @param strSearch - * text to search in the elements of specified container * @return boolean - true if any of the elements in container contains given * text */ public static boolean isContained(Collection container, String strSearch) { boolean bReturn = false; if ((container != null) && (!container.isEmpty())) { for (Iterator itrElements = container.iterator(); (itrElements.hasNext() && (!bReturn));) { if (((String) itrElements.next()).indexOf(strSearch) != -1) { bReturn = true; } } } return bReturn; } /** * Test if given string contains any element in the container. * * @param container - * container of which elements will be searched to see if they are * contained within given text * @param strSearch - * text to search in for the elements of specified container * @return boolean - true if the search text contains any of the elements in * container */ public static boolean contains(Collection container, String strSearch) { boolean bReturn = false; if ((container != null) && (!container.isEmpty())) { for (Iterator itrElements = container.iterator(); (itrElements.hasNext() && (!bReturn));) { if (strSearch.indexOf((String) itrElements.next()) != -1) { bReturn = true; } } } return bReturn; } /** * Method return boolean result if particular substring is contained within * the list of substrings separated by a separator. * * @param strSearchIn - * string of all substrings separated by separator to search in * @param strSearchFor - * string that will be search for * @param strSeparator - * item separator * @return boolean - true if it contains the ID, false otherwise */ public static boolean containsInSeparatedString(String strSearchIn, String strSearchFor, String strSeparator) { boolean bReturn = false; StringBuffer sbInputString = new StringBuffer(); StringBuffer sbSearchString = new StringBuffer(); if (strSearchIn.length() > 0) { // add separator at the beginning and end of the input string sbInputString.append(strSeparator); sbInputString.append(strSearchIn); sbInputString.append(strSeparator); // add separator at the beginning and end of the search string sbSearchString.append(strSeparator); sbSearchString.append(strSearchFor); sbSearchString.append(strSeparator); // search for particular ID if (sbInputString.indexOf(sbSearchString.toString()) != -1) { bReturn = true; } } return bReturn; } }