/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library 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;
* version 2.1 of the License.
*
* This library 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.
*/
package org.geotoolkit.util;
import org.geotoolkit.lang.Static;
import org.apache.sis.util.ArgumentChecks;
import static java.lang.Character.*;
/**
* Utility methods working on {@link String} or {@link CharSequence} instances.
*
* @author Martin Desruisseaux (Geomatys)
* @version 4.00
*
* @see org.apache.sis.util.CharSequences
*
* @since 3.09 (derived from 3.00)
* @module
*/
public final class Strings extends Static {
/**
* Do not allow instantiation of this class.
*/
private Strings() {
}
/**
* Returns {@code true} if the given identifier is a legal Java identifier.
* This method returns {@code true} if the identifier length is greater than zero,
* the first character is a {@linkplain Character#isJavaIdentifierStart(int) Java
* identifier start} and all remaining characters (if any) are
* {@linkplain Character#isJavaIdentifierPart(int) Java identifier parts}.
*
* @param identifier The character sequence to test.
* @return {@code true} if the given character sequence is a legal Java identifier.
* @throws NullPointerException if the argument is null.
*
* @since 3.20
*/
public static boolean isJavaIdentifier(final CharSequence identifier) {
final int length = identifier.length();
if (length == 0) {
return false;
}
int c = codePointAt(identifier, 0);
if (!isJavaIdentifierStart(c)) {
return false;
}
for (int i=0; (i += charCount(c)) < length;) {
c = codePointAt(identifier, i);
if (!isJavaIdentifierPart(c)) {
return false;
}
}
return true;
}
/**
* Returns {@code true} if every characters in the given character sequence are
* {@linkplain Character#isUpperCase(int) upper-case}.
*
* @param text The character sequence to test.
* @return {@code true} if every character are upper-case.
* @throws NullPointerException if the argument is null.
*
* @see String#toUpperCase()
*/
public static boolean isUpperCase(final CharSequence text) {
return isUpperCase(text, 0, text.length());
}
/**
* Same as {@link #isUpperCase(CharSequence)}, but on a sub-sequence.
*/
private static boolean isUpperCase(final CharSequence text, int lower, final int upper) {
while (lower < upper) {
final int c = codePointAt(text, lower);
if (!Character.isUpperCase(c)) {
return false;
}
lower += charCount(c);
}
return true;
}
/**
* Formats the given elements as a (typically) comma-separated list. This method is similar to
* {@link java.util.AbstractCollection#toString()} or {@link java.util.Arrays#toString(Object[])}
* except for the following:
*
* <ul>
* <li>There is no leading {@code '['} or trailing {@code ']'} characters.</li>
* <li>Null elements are ignored instead than formatted as {@code "null"}.</li>
* <li>If the {@code collection} argument is null or contains only null elements,
* then this method returns {@code null}.</li>
* <li>In the common case where the collection contains a single {@link String} element,
* that string is returned directly (no object duplication).</li>
* </ul>
*
* NOTE: In JDK8, this method can be replaced by {@link java.util.StringJoiner}.
*
* @param collection The elements to format in a (typically) comma-separated list, or {@code null}.
* @param separator The element separator, which is usually {@code ", "}.
* @return The (typically) comma-separated list, or {@code null} if the given {@code collection}
* was null or contains only null elements.
*
* @see java.util.StringJoiner
* @see java.util.Arrays#toString(Object[])
*/
public static String toString(final Iterable<?> collection, final String separator) {
ArgumentChecks.ensureNonNull("separator", separator);
String list = null;
if (collection != null) {
StringBuilder buffer = null;
for (final Object element : collection) {
if (element != null) {
if (list == null) {
list = element.toString();
} else {
if (buffer == null) {
buffer = new StringBuilder(list);
}
buffer.append(separator);
if (element instanceof CharSequence) {
// StringBuilder has numerous optimizations for this case.
buffer.append((CharSequence) element);
} else {
buffer.append(element);
}
}
}
}
if (buffer != null) {
list = buffer.toString();
}
}
return list;
}
}