/*
* Copyright (c) Thomas Parker, 2007, 2008.
* portions derived from CoreUtility.java
* Copyright 2002 (C) Bryan McRoberts <merton_monk@yahoo.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
package pcgen.base.lang;
import java.util.Collection;
import java.util.Comparator;
import java.util.StringTokenizer;
/**
* StringUtil is a utility class designed to provide utility methods when
* working with java.lang.String Objects.
*/
public final class StringUtil
{
/**
* Provides a Comparator for Strings that sorts in Case Sensitive Order.
* While this is generally the default for Strings (and thus this might seem
* extraneous), it is valuable as it can be used by other objects as a
* counterpart to String.CASE_INSENSITIVE_ORDER
*/
@SuppressWarnings("PMD.LongVariable")
public static final Comparator<String> CASE_SENSITIVE_ORDER = new Comparator<String>()
{
@Override
public int compare(String str1, String str2)
{
return str1.compareTo(str2);
}
};
private StringUtil()
{
// Do not instantiate
}
/**
* Concatenates the Collection of Objects (converted to Strings using
* .toString()) into a String using the separator as the delimiter.
*
* This method is value-semantic and will not modify or maintain a reference
* to the given Collection of Objects.
*
* @param collection
* An Collection of objects
* @param separator
* The separating string
* @return A 'separator' separated String
*/
public static String join(Collection<?> collection, String separator)
{
return joinToStringBuilder(collection, separator).toString();
}
/**
* Concatenates the Collection of Objects (converted to Strings using
* .toString()) into a StringBuilder using the separator as the delimiter.
*
* This method is value-semantic and will not modify or maintain a reference
* to the given Collection of Objects. Ownership of the returned
* StringBuilder is transferred to the calling object. No reference to the
* StringBuilder is maintained by StringUtil.
*
* @param collection
* An Collection of objects
* @param separator
* The separating character
* @return A 'separator' separated StringBuilder
*/
public static StringBuilder joinToStringBuilder(Collection<?> collection,
String separator)
{
if (collection == null)
{
return new StringBuilder();
}
StringBuilder result = new StringBuilder(collection.size() * 10);
boolean needjoin = false;
for (Object obj : collection)
{
if (needjoin)
{
result.append(separator);
}
needjoin = true;
result.append(obj.toString());
}
return result;
}
/**
* Concatenates the Array of Strings into a String using the separator as
* the delimiter.
*
* This method is value-semantic and will not modify or maintain a reference
* to the given Array of strings.
*
* @param stringArray
* An Array of strings
* @param separator
* The separating string
* @return A 'separator' separated String
*/
public static String join(String[] stringArray, String separator)
{
if (stringArray == null)
{
return "";
}
StringBuilder result = new StringBuilder(stringArray.length * 10);
boolean needjoin = false;
for (String obj : stringArray)
{
if (needjoin)
{
result.append(separator);
}
needjoin = true;
result.append(obj);
}
return result.toString();
}
/**
* Replaces all of the instances of the find String with newStr in the
* (first) given String.
*
* @param original
* The input String in which the String replacement should take
* place
* @param find
* The String to find within the input String, and which will be
* replaced by the newStr
* @param replace
* The new String that replaces the String to find within the
* input String
* @return A new String created as a result of modifying the input String to
* replace all instances of the String to find with the newStr
* replacement String
*/
public static String replaceAll(String original, String find, String replace)
{
int startindex = original.indexOf(find);
if (startindex < 0)
{
return original;
}
char[] working = original.toCharArray();
StringBuilder sb = new StringBuilder(original.length()
+ replace.length());
int currindex = 0;
while (startindex > -1)
{
for (int i = currindex; i < startindex; ++i)
{
sb.append(working[i]);
}
currindex = startindex;
sb.append(replace);
currindex += find.length();
startindex = original.indexOf(find, currindex);
}
for (int i = currindex; i < working.length; ++i)
{
sb.append(working[i]);
}
return sb.toString();
}
/**
* Tests to see if the given String has balanced parenthesis. Balanced means
* that it has an equal number of open and close parenthesis, and also that
* the parenthesis are in a "sensible" format. "Sensible" means that a close
* parenthesis cannot appear before an open parenthesis.
*
* @param str
* The String to be tested to see if it has balanced parenthesis
* @return true if the given String has balanced parenthesis; false
* otherwise
*/
public static boolean hasBalancedParens(String str)
{
int level = 0;
StringTokenizer st = new StringTokenizer(str, "()", true);
while (st.hasMoreTokens())
{
String tok = st.nextToken();
if (")".equals(tok))
{
level--;
}
else if ("(".equals(tok))
{
level++;
}
if (level < 0)
{
return false;
}
}
return level == 0;
}
}