You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/11/05 01:01:06 UTC
svn commit: r1031360 - in
/myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util:
ArrayUtils.java LocaleUtils.java RendererUtils.java StringUtils.java
Author: lu4242
Date: Fri Nov 5 00:01:06 2010
New Revision: 1031360
URL: http://svn.apache.org/viewvc?rev=1031360&view=rev
Log:
MFCOMMONS-15 Move and document some very useful classes from shared to myfaces commons utils
Added:
myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/ArrayUtils.java
myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/LocaleUtils.java
myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/RendererUtils.java
myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/StringUtils.java
Added: myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/ArrayUtils.java
URL: http://svn.apache.org/viewvc/myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/ArrayUtils.java?rev=1031360&view=auto
==============================================================================
--- myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/ArrayUtils.java (added)
+++ myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/ArrayUtils.java Fri Nov 5 00:01:06 2010
@@ -0,0 +1,229 @@
+/*
+ * 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.apache.myfaces.commons.util;
+
+import java.lang.reflect.Array;
+
+/**
+ * Utility class for managing arrays
+ *
+ * @since 1.0.1
+ * @author Anton Koinov (latest modification by $Author: matzew $)
+ * @version $Revision: 557350 $ $Date: 2007-07-18 13:19:50 -0500 (mié, 18 jul 2007) $
+ */
+public final class ArrayUtils
+{
+ public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ //~ Constructors -------------------------------------------------------------------------------
+
+ protected ArrayUtils()
+ {
+ // hide from public access
+ }
+
+ //~ Methods ------------------------------------------------------------------------------------
+
+ private static Class commonClass(Class c1, Class c2)
+ {
+ if (c1 == c2)
+ {
+ return c1;
+ }
+
+ if ((c1 == Object.class) || c1.isAssignableFrom(c2))
+ {
+ return c1;
+ }
+
+ if (c2.isAssignableFrom(c1))
+ {
+ return c2;
+ }
+
+ if (c1.isPrimitive() || c2.isPrimitive())
+ {
+ // REVISIT: we could try to autoconvert to Object or something appropriate
+ throw new IllegalArgumentException("incompatible types " + c1 + " and " + c2);
+ }
+
+ // REVISIT: we could try to find a common supper class or interface
+ return Object.class;
+ }
+
+ /**
+ * Concatenates two arrays into one. If arr1 is null or empty, returns arr2.
+ * If arr2 is null or empty, returns arr1. May return null if both arrays are null,
+ * or one is empty and the other null. <br>
+ * The concatenated array has componentType which is compatible with both input arrays (or Object[])
+ *
+ * @param arr1 input array
+ * @param arr2 input array
+ *
+ * @return Object the concatenated array, elements of arr1 first
+ */
+ public static Object concat(Object arr1, Object arr2)
+ {
+ int len1 = (arr1 == null) ? (-1) : Array.getLength(arr1);
+
+ if (len1 <= 0)
+ {
+ return arr2;
+ }
+
+ int len2 = (arr2 == null) ? (-1) : Array.getLength(arr2);
+
+ if (len2 <= 0)
+ {
+ return arr1;
+ }
+
+ Class commonComponentType =
+ commonClass(arr1.getClass().getComponentType(), arr2.getClass().getComponentType());
+ Object newArray = Array.newInstance(commonComponentType, len1 + len2);
+ System.arraycopy(arr1, 0, newArray, 0, len1);
+ System.arraycopy(arr2, 0, newArray, len1, len2);
+
+ return newArray;
+ }
+
+ /**
+ * Concatenates arrays into one. Any null or empty arrays are ignored.
+ * If all arrays are null or empty, returns null.
+ * Elements will be ordered in the order in which the arrays are supplied.
+ *
+ * @param arrs array of arrays
+ * @return the concatenated array
+ */
+ public static Object concat(Object[] arrs)
+ {
+ int totalLen = 0;
+ Class commonComponentType = null;
+ for (int i = 0, len = arrs.length; i < len; i++)
+ {
+ // skip all null arrays
+ if (arrs[i] == null)
+ {
+ continue;
+ }
+
+ int arrayLen = Array.getLength(arrs[i]);
+
+ // skip all empty arrays
+ if (arrayLen == 0)
+ {
+ continue;
+ }
+
+ totalLen += arrayLen;
+
+ Class componentType = arrs[i].getClass().getComponentType();
+ commonComponentType =
+ (commonComponentType == null) ? componentType
+ : commonClass(commonComponentType, componentType);
+ }
+
+ if (commonComponentType == null)
+ {
+ return null;
+ }
+
+ return concat(Array.newInstance(commonComponentType, totalLen), totalLen, arrs);
+ }
+
+ public static Object concat(Object toArray, int totalLen, Object[] arrs)
+ {
+ if (totalLen == 0)
+ {
+ // Should we allocate an empty array instead?
+ return toArray;
+ }
+
+ if (totalLen > Array.getLength(toArray))
+ {
+ toArray = Array.newInstance(toArray.getClass().getComponentType(), totalLen);
+ }
+
+ for (int i = 0, len = arrs.length, offset = 0; i < len; i++)
+ {
+ final Object arr = arrs[i];
+ if (arr != null)
+ {
+ int arrayLen = Array.getLength(arr);
+ if (arrayLen > 0)
+ {
+ System.arraycopy(arr, 0, toArray, offset, arrayLen);
+ offset += arrayLen;
+ }
+ }
+ }
+
+ return toArray;
+ }
+
+ public static Object concat(Object arr1, Object arr2, Object arr3)
+ {
+ return concat(new Object[] {arr1, arr2, arr3});
+ }
+
+ public static Object concat(Object arr1, Object arr2, Object arr3, Object arr4)
+ {
+ return concat(new Object[] {arr1, arr2, arr3, arr4});
+ }
+
+ public static Object concat(Object arr1, Object arr2, Object arr3, Object arr4, Object arr5)
+ {
+ return concat(new Object[] {arr1, arr2, arr3, arr4, arr5});
+ }
+
+ public static Object concatSameType(Object toArray, Object[] arrs)
+ {
+ int totalLen = 0;
+ for (int i = 0, len = arrs.length; i < len; i++)
+ {
+ if (arrs[i] != null)
+ {
+ totalLen += Array.getLength(arrs[i]);
+ }
+ }
+
+ return concat(toArray, totalLen, arrs);
+ }
+
+ public static boolean contains(Object[] array, Object value)
+ {
+ if (array == null || array.length == 0)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < array.length; i++)
+ {
+ Object o = array[i];
+ if ((o == null && value == null) ||
+ (o != null && o.equals(value)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
Added: myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/LocaleUtils.java
URL: http://svn.apache.org/viewvc/myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/LocaleUtils.java?rev=1031360&view=auto
==============================================================================
--- myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/LocaleUtils.java (added)
+++ myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/LocaleUtils.java Fri Nov 5 00:01:06 2010
@@ -0,0 +1,140 @@
+/*
+ * 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.apache.myfaces.commons.util;
+
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * @since 1.0.1
+ * @author Anton Koinov (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public final class LocaleUtils
+{
+ private static final Log log = LogFactory.getLog(LocaleUtils.class);
+
+ /** Utility class, do not instatiate */
+ private LocaleUtils()
+ {
+ // utility class, do not instantiate
+ }
+
+ /**
+ * Converts a locale string to <code>Locale</code> class. Accepts both
+ * '_' and '-' as separators for locale components.
+ *
+ * @param localeString string representation of a locale
+ * @return Locale instance, compatible with the string representation
+ */
+ public static Locale toLocale(String localeString)
+ {
+ if ((localeString == null) || (localeString.length() == 0))
+ {
+ Locale locale = Locale.getDefault();
+ if(log.isWarnEnabled())
+ log.warn("Locale name in faces-config.xml null or empty, setting locale to default locale : "+locale.toString());
+ return locale;
+ }
+
+ int separatorCountry = localeString.indexOf('_');
+ char separator;
+ if (separatorCountry >= 0) {
+ separator = '_';
+ }
+ else
+ {
+ separatorCountry = localeString.indexOf('-');
+ separator = '-';
+ }
+
+ String language, country, variant;
+ if (separatorCountry < 0)
+ {
+ language = localeString;
+ country = variant = "";
+ }
+ else
+ {
+ language = localeString.substring(0, separatorCountry);
+
+ int separatorVariant = localeString.indexOf(separator, separatorCountry + 1);
+ if (separatorVariant < 0)
+ {
+ country = localeString.substring(separatorCountry + 1);
+ variant = "";
+ }
+ else
+ {
+ country = localeString.substring(separatorCountry + 1, separatorVariant);
+ variant = localeString.substring(separatorVariant + 1);
+ }
+ }
+
+ return new Locale(language, country, variant);
+ }
+
+
+ /**
+ * Convert locale string used by converter tags to locale.
+ *
+ * @param name name of the locale
+ * @return locale specified by the given String
+ */
+ public static Locale converterTagLocaleFromString(String name)
+ {
+ try
+ {
+ Locale locale;
+ StringTokenizer st = new StringTokenizer(name, "_");
+ String language = st.nextToken();
+
+ if(st.hasMoreTokens())
+ {
+ String country = st.nextToken();
+
+ if(st.hasMoreTokens())
+ {
+ String variant = st.nextToken();
+ locale = new Locale(language, country, variant);
+ }
+ else
+ {
+ locale = new Locale(language, country);
+ }
+ }
+ else
+ {
+ locale = new Locale(language);
+ }
+
+
+ return locale;
+ }
+ catch(Exception e)
+ {
+ throw new IllegalArgumentException("Locale parsing exception - " +
+ "invalid string representation '" + name + "'");
+ }
+ }
+}
Added: myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/RendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/RendererUtils.java?rev=1031360&view=auto
==============================================================================
--- myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/RendererUtils.java (added)
+++ myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/RendererUtils.java Fri Nov 5 00:01:06 2010
@@ -0,0 +1,69 @@
+/*
+ * 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.apache.myfaces.commons.util;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * @author Leonardo Uribe
+ * @since 1.0.1
+ */
+public class RendererUtils
+{
+
+ public static void renderChildren(FacesContext facesContext, UIComponent component)
+ throws IOException
+ {
+ if (component.getChildCount() > 0)
+ {
+ for (Iterator it = component.getChildren().iterator(); it.hasNext(); )
+ {
+ UIComponent child = (UIComponent)it.next();
+ renderChild(facesContext, child);
+ }
+ }
+ }
+
+
+ public static void renderChild(FacesContext facesContext, UIComponent child)
+ throws IOException
+ {
+ if (!child.isRendered())
+ {
+ return;
+ }
+
+ child.encodeBegin(facesContext);
+ if (child.getRendersChildren())
+ {
+ child.encodeChildren(facesContext);
+ }
+ else
+ {
+ renderChildren(facesContext, child);
+ }
+ child.encodeEnd(facesContext);
+ }
+
+}
Added: myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/StringUtils.java
URL: http://svn.apache.org/viewvc/myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/StringUtils.java?rev=1031360&view=auto
==============================================================================
--- myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/StringUtils.java (added)
+++ myfaces/commons/trunk/myfaces-commons-utils/src/main/java/org/apache/myfaces/commons/util/StringUtils.java Fri Nov 5 00:01:06 2010
@@ -0,0 +1,710 @@
+/*
+ * 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.apache.myfaces.commons.util;
+
+import java.util.ArrayList;
+
+
+/**
+ * Implements utility functions for the String class
+ *
+ * <p>
+ * Emphasis on performance and reduced memory allocation/garbage collection
+ * in exchange for longer more complex code.
+ * </p>
+ *
+ * @since 1.0.1
+ * @author Anton Koinov (latest modification by $Author: skitching $)
+ * @version $Revision: 673827 $ $Date: 2008-07-03 16:46:23 -0500 (jue, 03 jul 2008) $
+ */
+public final class StringUtils
+{
+ private StringUtils()
+ {
+ // utility class, no instantiation
+ }
+
+ //~ Methods ------------------------------------------------------------------------------------
+
+ /**
+ * Checks that the string represents a floating point number that CANNOT be
+ * in exponential notation
+ *
+ * @param str the string to check
+ *
+ * @return boolean
+ */
+ public static boolean isFloatNoExponent(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ return false;
+ }
+
+ // skip first char if sign char
+ char c = str.charAt(0);
+ int i = ((c == '-') || (c == '+')) ? 1 : 0;
+
+ // is it only a sign?
+ if (i >= len)
+ {
+ return false;
+ }
+
+ boolean decimalPointFound = false;
+
+ do
+ {
+ c = str.charAt(i);
+ if (c == '.')
+ {
+ // is this a second dot?
+ if (decimalPointFound)
+ {
+ return false;
+ }
+
+ decimalPointFound = true;
+ }
+ else if (!Character.isDigit(c))
+ {
+ return false;
+ }
+
+ i++;
+ }
+ while (i < len);
+
+ return true;
+ }
+
+ public static boolean isFloatWithOptionalExponent(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ return false;
+ }
+
+ // skip first char if sign char
+ char c = str.charAt(0);
+ int i = ((c == '-') || (c == '+')) ? 1 : 0;
+
+ // is it only a sign?
+ if (i >= len)
+ {
+ return false;
+ }
+
+ boolean exponentFound = false;
+ boolean decimalPointFound = false;
+
+ do
+ {
+ c = str.charAt(i);
+ switch (c)
+ {
+ case '.':
+
+ // is this a second one, are we in the exponent?
+ if (decimalPointFound || exponentFound)
+ {
+ return false;
+ }
+ decimalPointFound = true;
+
+ break;
+
+ case 'e':
+ case 'E':
+
+ // is this a second one?
+ if (exponentFound)
+ {
+ return false;
+ }
+ exponentFound = true;
+
+ // check for exponent sign
+ c = str.charAt(i + 1);
+
+ if ((c == '-') || (c == '+'))
+ {
+ i++;
+ }
+
+ break;
+
+ default:
+ if (!Character.isDigit(c))
+ {
+ return false;
+ }
+ }
+
+ i++;
+ }
+ while (i < len);
+
+ return true;
+ }
+
+ public static boolean isInteger(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ return false;
+ }
+
+ // skip first char if sign char
+ char c = str.charAt(0);
+ int i = ((c == '-') || (c == '+')) ? 1 : 0;
+
+ // is it only a sign?
+ if (i >= len)
+ {
+ return false;
+ }
+
+ do
+ {
+ if (!Character.isDigit(str.charAt(i)))
+ {
+ return false;
+ }
+ i++;
+ }
+ while (i < len);
+
+ return true;
+ }
+
+ public static boolean isUnsignedInteger(String str)
+ {
+ int len = str.length();
+ if (len == 0)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (!Character.isDigit(str.charAt(i)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Undoubles the quotes inside the string <br> Example:<br>
+ * <pre>
+ * hello""world becomes hello"world
+ * </pre>
+ *
+ * @param str input string to dequote
+ * @param quote the quoting char
+ *
+ * @return dequoted string
+ */
+ public static String dequote(String str, char quote)
+ {
+ // Is there anything to dequote?
+ if (str == null)
+ {
+ return null;
+ }
+
+ return dequote(str, 0, str.length(), quote);
+ }
+
+ /**
+ * Undoubles the quotes inside a substring <br> Example:<br>
+ * <pre>
+ * hello""world becomes hello"world
+ * </pre>
+ * WARNING: scan for quote may continue to the end of the string, make sure
+ * that either <code>charAt(end + 1) == quote</code> or <code>end =
+ * str.lentgth()</code>. If in doubt call
+ * <code>dequote(str.substring(begin, end), quote)</code>
+ *
+ * @param str input string from which to get the substring, must not be
+ * null
+ * @param begin begin index for substring
+ * @param end end index for substring
+ * @param quote the quoting char
+ *
+ * @return dequoted string
+ *
+ * @throws IllegalArgumentException if string is incorrectly quoted
+ */
+ public static String dequote(String str, int begin, int end, char quote)
+ {
+ // Is there anything to dequote?
+ if (begin == end)
+ {
+ return "";
+ }
+
+ int end_ = str.indexOf(quote, begin);
+
+ // If no quotes, return the original string
+ // and save StringBuffer allocation/char copying
+ if (end_ < 0)
+ {
+ return str.substring(begin, end);
+ }
+
+ StringBuffer sb = new StringBuffer(end - begin);
+ int begin_ = begin; // need begin later
+ for (; (end_ >= 0) && (end_ < end);
+ end_ = str.indexOf(quote, begin_ = end_ + 2))
+ {
+ if (((end_ + 1) >= end) || (str.charAt(end_ + 1) != quote))
+ {
+ throw new IllegalArgumentException(
+ "Internal quote not doubled in string '"
+ + str.substring(begin, end) + "'");
+ }
+
+ sb.append(substring(str, begin_, end_)).append(quote);
+ }
+
+ return sb.append(substring(str, begin_, end)).toString();
+ }
+
+ /**
+ * Removes the surrounding quote and any double quote inside the string <br>
+ * Example:<br>
+ * <pre>
+ * "hello""world" becomes hello"world
+ * </pre>
+ *
+ * @param str input string to dequote
+ * @param quote the quoting char
+ *
+ * @return dequoted String
+ */
+ public static String dequoteFull(String str, char quote)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+
+ return dequoteFull(str, 0, str.length(), quote);
+ }
+
+ public static String dequoteFull(String str, int begin, int end, char quote)
+ {
+ // If empty substring, return empty string
+ if (begin == end)
+ {
+ return "";
+ }
+
+ // If not quoted, return string
+ if (str.charAt(begin) != quote)
+ {
+ return str.substring(begin, end);
+ }
+
+ int _end = end - 1;
+ if ((str.length() < 2) || (str.charAt(_end) != quote))
+ {
+ throw new IllegalArgumentException(
+ "Closing quote missing in string '"
+ + substring(str, begin, end) + "'");
+ }
+
+ return dequote(str, begin + 1, _end, quote);
+ }
+
+ public static String replace(String str, String repl, String with)
+ {
+ int lastindex = 0;
+ int pos = str.indexOf(repl);
+
+ // If no replacement needed, return the original string
+ // and save StringBuffer allocation/char copying
+ if (pos < 0)
+ {
+ return str;
+ }
+
+ int len = repl.length();
+ int lendiff = with.length() - repl.length();
+ StringBuffer out =
+ new StringBuffer((lendiff <= 0) ? str.length()
+ : (str.length() + (10 * lendiff)));
+ for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + len))
+ {
+ out.append(substring(str, lastindex, pos)).append(with);
+ }
+
+ return out.append(substring(str, lastindex, str.length())).toString();
+ }
+
+ public static String replace(String str, char repl, String with)
+ {
+ int pos = str.indexOf(repl);
+
+ // If no replacement needed, return the original string
+ // and save StringBuffer allocation/char copying
+ if (pos < 0)
+ {
+ return str;
+ }
+
+ int len = str.length();
+ int lendiff = with.length() - 1;
+ StringBuffer out =
+ new StringBuffer((lendiff <= 0) ? str.length()
+ : (str.length() + (10 * lendiff)));
+ int lastindex = 0;
+ for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + 1))
+ {
+ out.append(substring(str, lastindex, pos)).append(with);
+ }
+
+ return out.append(substring(str, lastindex, len)).toString();
+ }
+
+ public static StringBuffer replace(
+ StringBuffer out, String s, String repl, String with)
+ {
+ int lastindex = 0;
+ int len = repl.length();
+ for (int index = s.indexOf(repl); index >= 0;
+ index = s.indexOf(repl, lastindex = index + len))
+ {
+ // we have search string at position index
+ out.append(substring(s, lastindex, index)).append(with);
+ }
+
+ return out.append(substring(s, lastindex, len));
+ }
+
+ /**
+ * Split a string into an array of strings arround a character separator.
+ * This function will be efficient for longer strings
+ *
+ * @param str the string to be split
+ * @param separator the separator character
+ *
+ * @return array of string subparts
+ */
+ public static String[] splitLongString(String str, char separator)
+ {
+ int len;
+ if (str == null || (len = str.length()) == 0)
+ {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ int oldPos = 0;
+ ArrayList list = new ArrayList();
+ for (
+ int pos = str.indexOf(separator); pos >= 0;
+ pos = str.indexOf(separator, (oldPos = (pos + 1))))
+ {
+ list.add(substring(str, oldPos, pos));
+ }
+
+ list.add(substring(str, oldPos, len));
+
+ return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
+ }
+
+ /**
+ * Split a string into an array of strings arround a character separator.
+ * Each element can be optionally quoted by the quote character.<br>
+ * This function will be efficient for long strings
+ *
+ * @param str the string to be split
+ * @param separator the separator character
+ * @param quote the quote character
+ *
+ * @return array of string subparts
+ *
+ * @throws IllegalArgumentException DOCUMENT ME!
+ */
+ public static String[] splitLongString(
+ String str, char separator, char quote)
+ {
+ int len;
+ if (str == null || (len = str.length()) == 0)
+ {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ int oldPos = 0;
+ ArrayList list = new ArrayList();
+ for (int pos = 0; pos < len; oldPos = ++pos)
+ {
+ // Skip quoted text, if any
+ while ((pos < len) && (str.charAt(pos) == quote))
+ {
+ pos = str.indexOf(quote, pos + 1) + 1;
+
+ if (pos == 0)
+ {
+ throw new IllegalArgumentException(
+ "Closing quote missing in string '" + str + "'");
+ }
+ }
+
+ boolean quoted;
+
+ if (pos != oldPos)
+ {
+ quoted = true;
+
+ if ((pos < len) && (str.charAt(pos) != separator))
+ {
+ throw new IllegalArgumentException(
+ "Separator must follow closing quote in string '"
+ + str + "'");
+ }
+ }
+ else
+ {
+ quoted = false;
+ pos = str.indexOf(separator, pos);
+ if (pos < 0)
+ {
+ pos = len;
+ }
+ }
+
+ list.add(
+ quoted ? dequote(str, oldPos + 1, pos - 1, quote)
+ : substring(str, oldPos, pos));
+ }
+
+ return (String[]) list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
+ }
+
+ /**
+ * Split a string into an array of strings arround a character separator.
+ * This function will be efficient for short strings, for longer strings,
+ * another approach may be better
+ *
+ * @param str the string to be split
+ * @param separator the separator character
+ *
+ * @return array of string subparts
+ */
+ public static String[] splitShortString(String str, char separator)
+ {
+ int len;
+ if (str == null || (len = str.length()) == 0)
+ {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ int lastTokenIndex = 0;
+
+ // Step 1: how many substrings?
+ // We exchange double scan time for less memory allocation
+ for (int pos = str.indexOf(separator);
+ pos >= 0; pos = str.indexOf(separator, pos + 1))
+ {
+ lastTokenIndex++;
+ }
+
+ // Step 2: allocate exact size array
+ String[] list = new String[lastTokenIndex + 1];
+
+ int oldPos = 0;
+
+ // Step 3: retrieve substrings
+ for (
+ int pos = str.indexOf(separator), i = 0; pos >= 0;
+ pos = str.indexOf(separator, (oldPos = (pos + 1))))
+ {
+ list[i++] = substring(str, oldPos, pos);
+ }
+
+ list[lastTokenIndex] = substring(str, oldPos, len);
+
+ return list;
+ }
+
+ /**
+ * Split a string into an array of strings arround a character separator.
+ * Each element can be optionally quoted by the quote character.<br>
+ * This function will be efficient for short strings, for longer strings,
+ * another approach may be better
+ *
+ * @param str the string to be split
+ * @param separator the separator character
+ * @param quote the quote character
+ *
+ * @return array of string subparts
+ *
+ * @throws IllegalArgumentException DOCUMENT ME!
+ */
+ public static String[] splitShortString(
+ String str, char separator, char quote)
+ {
+ int len;
+ if (str == null || (len = str.length()) == 0)
+ {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ // Step 1: how many substrings?
+ // We exchange double scan time for less memory allocation
+ int tokenCount = 0;
+ for (int pos = 0; pos < len; pos++)
+ {
+ tokenCount++;
+
+ int oldPos = pos;
+
+ // Skip quoted text, if any
+ while ((pos < len) && (str.charAt(pos) == quote))
+ {
+ pos = str.indexOf(quote, pos + 1) + 1;
+
+ // pos == 0 is not found (-1 returned by indexOf + 1)
+ if (pos == 0)
+ {
+ throw new IllegalArgumentException(
+ "Closing quote missing in string '" + str + "'");
+ }
+ }
+
+ if (pos != oldPos)
+ {
+ if ((pos < len) && (str.charAt(pos) != separator))
+ {
+ throw new IllegalArgumentException(
+ "Separator must follow closing quote in strng '"
+ + str + "'");
+ }
+ }
+ else
+ {
+ pos = str.indexOf(separator, pos);
+ if (pos < 0)
+ {
+ break;
+ }
+ }
+ }
+
+ // Main loop will finish one substring short when last char is separator
+ if (str.charAt(len - 1) == separator)
+ {
+ tokenCount++;
+ }
+
+ // Step 2: allocate exact size array
+ String[] list = new String[tokenCount];
+
+ // Step 3: retrieve substrings
+ // Note: on this pass we do not check for correctness,
+ // since we have already done so
+ tokenCount--; // we want to stop one token short
+
+ int oldPos = 0;
+ for (int pos = 0, i = 0; i < tokenCount; i++, oldPos = ++pos)
+ {
+ boolean quoted;
+
+ // Skip quoted text, if any
+ while (str.charAt(pos) == quote)
+ {
+ pos = str.indexOf(quote, pos + 1) + 1;
+ }
+
+ if (pos != oldPos)
+ {
+ quoted = true;
+
+ if (str.charAt(pos) != separator)
+ {
+ throw new IllegalArgumentException(
+ "Separator must follow closing quote in strng '"
+ + str + "'");
+ }
+ }
+ else
+ {
+ quoted = false;
+ pos = str.indexOf(separator, pos);
+ }
+
+ list[i] =
+ quoted ? dequote(str, oldPos + 1, pos - 1, quote)
+ : substring(str, oldPos, pos);
+ }
+
+ list[tokenCount] = dequoteFull(str, oldPos, len, quote);
+
+ return list;
+ }
+
+ public static String substring(String str, int begin, int end)
+ {
+ if (begin == end)
+ {
+ return "";
+ }
+
+ return str.substring(begin, end);
+ }
+
+ public static String[] trim(String[] strings)
+ {
+ if (strings == null)
+ {
+ return null;
+ }
+
+ for (int i = 0, len = strings.length; i < len; i++)
+ {
+ strings[i] = strings[i].trim();
+ }
+
+ return strings;
+ }
+
+ /**
+ * Returns the minimum index >= 0, if any
+ *
+ * <p>
+ * Use to find the first of two characters in a string:<br>
+ * <code>minIndex(s.indexOf('/'), indexOf('\'))</code>
+ * </p>
+ *
+ */
+ public static int minIndex(int a, int b)
+ {
+ return (a < 0) ? b
+ : (b < 0) ? a
+ : (a < b) ? a : b;
+ }
+}