From commits-return-527-apmail-sis-commits-archive=sis.apache.org@sis.apache.org Mon Sep 24 10:49:34 2012 Return-Path: X-Original-To: apmail-sis-commits-archive@www.apache.org Delivered-To: apmail-sis-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 32595D7F8 for ; Mon, 24 Sep 2012 10:49:34 +0000 (UTC) Received: (qmail 98703 invoked by uid 500); 24 Sep 2012 10:49:33 -0000 Delivered-To: apmail-sis-commits-archive@sis.apache.org Received: (qmail 98656 invoked by uid 500); 24 Sep 2012 10:49:33 -0000 Mailing-List: contact commits-help@sis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sis-dev@sis.apache.org Delivered-To: mailing list commits@sis.apache.org Received: (qmail 98649 invoked by uid 99); 24 Sep 2012 10:49:33 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 24 Sep 2012 10:49:33 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 24 Sep 2012 10:49:23 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 719DC238899C for ; Mon, 24 Sep 2012 10:48:38 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1389286 [2/2] - in /sis/trunk/sis-utility/src: main/java/org/apache/sis/resources/ main/java/org/apache/sis/util/ test/java/org/apache/sis/util/ Date: Mon, 24 Sep 2012 10:48:38 -0000 To: commits@sis.apache.org From: desruisseaux@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120924104838.719DC238899C@eris.apache.org> Copied: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java (from r1388393, sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java) URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java?p2=sis/trunk/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java&p1=sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java&r1=1388393&r2=1389286&rev=1389286&view=diff ============================================================================== --- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java (original) +++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java Mon Sep 24 10:48:37 2012 @@ -19,57 +19,27 @@ package org.apache.sis.util; import org.apache.sis.resources.Errors; import static java.lang.Character.*; -import static java.util.Arrays.fill; -import static java.util.Arrays.copyOf; -import static org.apache.sis.util.Arrays.resize; /** - * Utility methods working on {@link CharSequence} or {@link String} instances. Some methods - * defined in this class duplicate the functionalities already provided in the {@code String} - * class, but works on a generic {@code CharSequence} instance instead than {@code String}. - * Other methods perform their work directly on a provided {@link StringBuilder} instance. + * Utility methods working on {@link StringBuilder} instances. Some methods defined in this + * class duplicate the functionalities provided in the {@link CharSequences} class, but + * modify directly the content of the provided {@code StringBuilder} instead than creating + * new objects. * * {@section Unicode support} * Every methods defined in this class work on code points instead than characters * when appropriate. Consequently those methods should behave correctly with characters outside * the Basic Multilingual Plane (BMP). * - * {@section Handling of null values} - * Some methods accept a {@code null} argument, in particular the methods converting the - * given {@code String} to another {@code String} which may be the same. For example the - * {@link #camelCaseToAcronym(String)} method returns {@code null} if the string to convert is - * {@code null}. Some other methods like {@link #count(String, char)} handles {@code null} - * argument as synonymous to an empty string. The methods that do not accept a {@code null} - * argument are explicitly documented as throwing a {@link NullPointerException}. - * * @author Martin Desruisseaux (Geomatys) * @since 0.3 (derived from geotk-3.00) * @version 0.3 * @module * - * @see java.util.Arrays#toString(Object[]) + * @see CharSequences */ -public final class CharSequences extends Static { - /** - * An array of zero-length. This constant play a role equivalents to - * {@link java.util.Collections#EMPTY_LIST}. - */ - public static final String[] EMPTY = new String[0]; - - /** - * An array of strings containing only white spaces. String lengths are equal to their - * index in the {@code spaces} array. For example, {@code spaces[4]} contains a string - * of length 4. Strings are constructed only when first needed. - */ - private static final String[] SPACES = new String[21]; - static { - final int last = SPACES.length - 1; - final char[] spaces = new char[last]; - fill(spaces, ' '); - SPACES[last] = new String(spaces).intern(); - } - +public final class StringBuilders extends Static { /** * Letters in the range 00C0 (192) to 00FF (255) inclusive with their accent removed, * when possible. @@ -80,348 +50,28 @@ public final class CharSequences extends /** * Do not allow instantiation of this class. */ - private CharSequences() { - } - - /** - * Returns the code point after the given index. This method completes - * {@link String#codePointBefore(int)} but is rarely used because slightly inefficient - * (in most cases, the code point at {@code index} and its the {@code charCount(int)} - * value are already known, so the method calls performed here would be unnecessary). - */ - private static int codePointAfter(final CharSequence text, final int index) { - return codePointAt(text, index + charCount(codePointAt(text, index))); - } - - /** - * Returns a string of the specified length filled with white spaces. - * This method tries to return a pre-allocated string if possible. - * - * @param length The string length. Negative values are clamped to 0. - * @return A string of length {@code length} filled with white spaces. - */ - public static String spaces(int length) { - /* - * No need to synchronize. In the unlikely event of two threads calling this method - * at the same time and the two calls creating a new string, the String.intern() call - * will take care of canonicalizing the strings. - */ - if (length < 0) { - length = 0; - } - String s; - if (length < SPACES.length) { - s = SPACES[length]; - if (s == null) { - s = SPACES[SPACES.length - 1].substring(0, length).intern(); - SPACES[length] = s; - } - } else { - final char[] spaces = new char[length]; - fill(spaces, ' '); - s = new String(spaces); - } - return s; - } - - /** - * Returns the {@linkplain CharSequence#length() length} of the given characters sequence, - * or 0 if {@code null}. - * - * @param text The character sequence from which to get the length, or {@code null}. - * @return The length of the character sequence, or 0 if the argument is {@code null}. - */ - public static int length(final CharSequence text) { - return (text != null) ? text.length() : 0; - } - - /** - * Returns the number of occurrences of the {@code toSearch} string in the given {@code text}. - * The search is case-sensitive. - * - * @param text String to search in, or {@code null}. - * @param toSearch The string to search in the given {@code text}. - * Must contain at least one character. - * @return The number of occurrence of {@code toSearch} in {@code text}, - * or 0 if {@code text} was null or empty. - * @throws IllegalArgumentException If the {@code toSearch} array is null or empty. - */ - public static int count(final String text, final String toSearch) { - final int length; - if (toSearch == null || (length = toSearch.length()) == 0) { - throw new IllegalArgumentException(Errors.format( - Errors.Keys.EmptyArgument_1, "toSearch")); - } - if (length == 1) { - return count(text, toSearch.charAt(0)); - } - int n = 0; - if (text != null) { - for (int i=text.indexOf(toSearch); i>=0; i=text.indexOf(toSearch, i+length)) { - n++; - } - } - return n; - } - - /** - * Counts the number of occurrence of the given character in the given string. This - * method performs the same work than {@link #count(CharSequence, char)}, but is faster. - * - * @param text The text in which to count the number of occurrence. - * @param c The character to count, or 0 if {@code text} was null. - * @return The number of occurrences of the given character. - */ - public static int count(final String text, final char c) { - int n = 0; - if (text != null) { - for (int i=text.indexOf(c); ++i!=0; i=text.indexOf(c, i)) { - n++; - } - } - return n; - } - - /** - * Counts the number of occurrence of the given character in the given character sequence. - * This method performs the same work than {@link #count(String, char)}, but on a more - * generic interface. - * - * @param text The text in which to count the number of occurrence. - * @param c The character to count, or 0 if {@code text} was null. - * @return The number of occurrences of the given character. - */ - public static int count(final CharSequence text, final char c) { - if (text instanceof String) { - return count((String) text, c); - } - int n = 0; - if (text != null) { - // No need to use the code point API here, since we are looking for exact matches. - for (int i=text.length(); --i>=0;) { - if (text.charAt(i) == c) { - n++; - } - } - } - return n; - } - - /** - * Splits a string around the given character. The array returned by this method contains each - * substring of the given string that is terminated by the given character or is terminated by - * the end of the string. The substrings in the array are in the order in which they occur in - * the given string. If the character is not found in the input, then the resulting array has - * just one element, namely the given string. - *

- * This method is similar to the standard {@link String#split(String)} method except for the - * following: - *

- *

    - *
  • It accepts a {@code null} input string, in which case an empty array is returned.
  • - *
  • The separator is a simple character instead than a regular expression.
  • - *
  • The leading and trailing spaces of each substring are {@linkplain String#trim trimmed}.
  • - *
- * - * @param toSplit The string to split, or {@code null}. - * @param separator The delimiting character (typically the coma). - * @return The array of strings computed by splitting the given string around the given - * character, or an empty array if {@code toSplit} was null. - * - * @see String#split(String) - */ - public static String[] split(final String toSplit, final char separator) { - final boolean excludeEmpty = (separator <= ' '); // Use the same criterion than String.trim(). - String[] strings = new String[4]; - int count = 0; - if (toSplit != null) { - int last = 0; - for (int i=toSplit.indexOf(separator); i>=0; i=toSplit.indexOf(separator, i)) { - // Note: parseDoubles(...) needs the call to trim(). - final String item = toSplit.substring(last, i).trim(); - if (!excludeEmpty || !item.isEmpty()) { - if (count == strings.length) { - strings = copyOf(strings, count << 1); - } - strings[count++] = item; - } - last = ++i; - } - final String item = toSplit.substring(last).trim(); - if (!excludeEmpty || !item.isEmpty()) { - if (count == strings.length) { - strings = copyOf(strings, count + 1); - } - strings[count++] = item; - } - } - return resize(strings, count); - } - - /** - * {@linkplain #split(String, char) Splits} the given string around the given character, - * then {@linkplain Double#parseDouble(String) parses} each item as a {@code double}. - * - * @param values The strings containing the values to parse, or {@code null}. - * @param separator The delimiting character (typically the coma). - * @return The array of numbers parsed from the given string, - * or an empty array if {@code values} was null. - * @throws NumberFormatException If at least one number can not be parsed. - */ - public static double[] parseDoubles(final String values, final char separator) throws NumberFormatException { - final String[] tokens = split(values, separator); - final double[] parsed = new double[tokens.length]; - for (int i=0; i - *
    - *
  • There is no leading {@code '['} and trailing {@code ']'} characters.
  • - *
  • Null elements are ignored instead than formatted as {@code "null"}.
  • - *
  • If the {@code collection} argument is null or contains only null elements, - * then this method returns {@code null}.
  • - *
  • In the common case where the collection contains a single {@link String} element, - * that string is returned directly (no object duplication).
  • - *
- *

- * This method is the converse of {@link #getLinesFromMultilines(String)} - * when the separator is {@link System#lineSeparator()}. + * @param buffer The string in which to perform the replacements. + * @param toSearch The character to replace. + * @param replaceBy The replacement for the searched character. + * @throws NullArgumentException If the {@code buffer} arguments is null. * - * @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 String#replace(char, char) */ - public static String formatList(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).append(element); - } + public static void replace(final StringBuilder buffer, final char toSearch, final char replaceBy) { + ArgumentChecks.ensureNonNull("buffer", buffer); + if (toSearch != replaceBy) { + for (int i=buffer.length(); --i>=0;) { + if (buffer.charAt(i) == toSearch) { + buffer.setCharAt(i, replaceBy); } } - if (buffer != null) { - list = buffer.toString(); - } } - return list; } /** @@ -429,21 +79,25 @@ public final class CharSequences extends * This method invokes {@link StringBuilder#replace(int, int, String)} * for each occurrence of {@code search} found in the buffer. * - * @param buffer The string in which to perform the replacements. - * @param search The string to replace. - * @param replacement The replacement for the target string. - * @throws NullPointerException if any of the arguments is null. + * @param buffer The string in which to perform the replacements. + * @param toSearch The string to replace. + * @param replaceBy The replacement for the searched string. + * @throws NullArgumentException If any of the arguments is null. + * @throws IllegalArgumentException If the {@code toSearch} argument is empty. * * @see String#replace(char, char) * @see String#replace(CharSequence, CharSequence) * @see StringBuilder#replace(int, int, String) */ - public static void replace(final StringBuilder buffer, final String search, final String replacement) { - if (!search.equals(replacement)) { - final int length = search.length(); + public static void replace(final StringBuilder buffer, final String toSearch, final String replaceBy) { + ArgumentChecks.ensureNonNull ("buffer", buffer); + ArgumentChecks.ensureNonEmpty("toSearch", toSearch); + ArgumentChecks.ensureNonNull ("replaceBy", replaceBy); + if (!toSearch.equals(replaceBy)) { + final int length = toSearch.length(); int i = buffer.length(); - while ((i = buffer.lastIndexOf(search, i)) >= 0) { - buffer.replace(i, i+length, replacement); + while ((i = buffer.lastIndexOf(toSearch, i)) >= 0) { + buffer.replace(i, i+length, replaceBy); i -= length; } } @@ -454,15 +108,17 @@ public final class CharSequences extends * The substring to be replaced begins at the specified {@code start} and extends to the * character at index {@code end - 1}. * - * @param buffer The buffer in which to perform the replacement. - * @param start The beginning index in the {@code buffer}, inclusive. - * @param end The ending index in the {@code buffer}, exclusive. - * @param chars The array that will replace previous contents. - * @throws NullPointerException if the {@code buffer} or {@code chars} argument is null. + * @param buffer The buffer in which to perform the replacement. + * @param start The beginning index in the {@code buffer}, inclusive. + * @param end The ending index in the {@code buffer}, exclusive. + * @param chars The array that will replace previous contents. + * @throws NullArgumentException if the {@code buffer} or {@code chars} argument is null. * * @see StringBuilder#replace(int, int, String) */ public static void replace(final StringBuilder buffer, int start, final int end, final char[] chars) { + ArgumentChecks.ensureNonNull("buffer", buffer); + ArgumentChecks.ensureNonNull("chars", chars); int length = end - start; if (start < 0 || length < 0) { throw new StringIndexOutOfBoundsException(Errors.format(Errors.Keys.IllegalRange_2, start, end)); @@ -485,106 +141,44 @@ public final class CharSequences extends * {@link StringBuilder#delete(int, int)} for each occurrence of {@code search} found in * the buffer. * - * @param buffer The string in which to perform the removals. - * @param search The string to remove. - * @throws NullPointerException if any of the arguments is null. + * @param buffer The string in which to perform the removals. + * @param toSearch The string to remove. + * @throws NullPointerException If any of the arguments is null. + * @throws IllegalArgumentException If the {@code toSearch} argument is empty. * * @see StringBuilder#delete(int, int) */ - public static void remove(final StringBuilder buffer, final String search) { - final int length = search.length(); - for (int i=buffer.lastIndexOf(search); i>=0; i=buffer.lastIndexOf(search, i)) { + public static void remove(final StringBuilder buffer, final String toSearch) { + ArgumentChecks.ensureNonNull ("buffer", buffer); + ArgumentChecks.ensureNonEmpty("toSearch", toSearch); + final int length = toSearch.length(); + for (int i=buffer.lastIndexOf(toSearch); i>=0; i=buffer.lastIndexOf(toSearch, i)) { buffer.delete(i, i + length); } } /** - * Returns a string with leading and trailing white spaces omitted. White spaces are identified - * by the {@link Character#isWhitespace(int)} method. - *

- * This method is similar in purpose to {@link String#trim()}, except that the later considers - * every ASCII control codes below 32 to be a whitespace. This have the effect of removing - * {@linkplain org.apache.sis.io.X364 X3.64} escape sequences as well. Users should invoke - * this {@code CharSequences.trim} method instead if they need to preserve X3.64 escape sequences. - * - * @param text The string from which to remove leading and trailing white spaces, or {@code null}. - * @return A string with leading and trailing white spaces removed, or {@code null} is the given - * string was null. - * - * @see String#trim() - */ - public static String trim(String text) { - if (text != null) { - int upper = text.length(); - while (upper != 0) { - final int c = text.codePointBefore(upper); - if (!isWhitespace(c)) break; - upper -= charCount(c); - } - int lower = 0; - while (lower < upper) { - final int c = text.codePointAt(lower); - if (!isWhitespace(c)) break; - lower += charCount(c); - } - text = text.substring(lower, upper); - } - return text; - } - - /** * Trims the fractional part of the given formatted number, provided that it doesn't change * the value. This method assumes that the number is formatted in the US locale, typically * by the {@link Double#toString(double)} method. *

- * More specifically if the given string ends with a {@code '.'} character followed by a - * sequence of {@code '0'} characters, then those characters are omitted. Otherwise this - * method returns the string unchanged. This is a "all or nothing" method: - * either the fractional part is completely removed, or either it is left unchanged. - * - * {@section Examples} - * This method returns {@code "4"} if the given value is {@code "4."}, {@code "4.0"} or - * {@code "4.00"}, but returns {@code "4.10"} unchanged (including the trailing {@code '0'} - * character) if the input is {@code "4.10"}. - * - * {@section Use case} - * This method is useful before to {@linkplain Integer#parseInt(String) parse a number} - * if that number should preferably be parsed as an integer before attempting to parse - * it as a floating point number. - * - * @param value The value to trim if possible, or {@code null}. - * @return The value without the trailing {@code ".0"} part (if any), - * or {@code null} if the given string was null. - */ - public static String trimFractionalPart(final String value) { - if (value != null) { - for (int i=value.length(); i>0;) { - final int c = value.codePointBefore(i); - i -= charCount(c); - switch (c) { - case '0': continue; - case '.': return value.substring(0, i); - default : return value; - } - } - } - return value; - } - - /** - * Trims the fractional part of the given formatted number, provided that it doesn't change - * the value. This method performs the same work than {@link #trimFractionalPart(String)} - * except that it modifies the given buffer in-place. + * More specifically if the given buffer ends with a {@code '.'} character followed by a + * sequence of {@code '0'} characters, then those characters are removed. Otherwise this + * method does nothing. This is a "all or nothing" method: either the fractional + * part is completely removed, or either it is left unchanged. * * {@section Use case} * This method is useful after a {@linkplain StringBuilder#append(double) double value has * been appended to the buffer}, in order to make it appears like an integer when possible. * * @param buffer The buffer to trim if possible. - * @throws NullPointerException if the argument is null. + * @throws NullArgumentException If the given {@code buffer} is null. + * + * @see CharSequences#trimFractionalPart(CharSequence) */ @SuppressWarnings("fallthrough") public static void trimFractionalPart(final StringBuilder buffer) { + ArgumentChecks.ensureNonNull ("buffer", buffer); for (int i=buffer.length(); i > 0;) { final int c = buffer.codePointBefore(i); i -= charCount(c); @@ -602,18 +196,22 @@ public final class CharSequences extends *

* The current implementation replaces only the characters in the range {@code 00C0} * to {@code 00FF}, inclusive. Other characters are left unchanged. - *

- * Note that if the given character sequence is an instance of {@link StringBuilder}, - * then the replacement will be performed in-place. * - * @param text The text to scan for Unicode characters to replace by ASCII characters, - * or {@code null}. - * @return The given text with substitution applied, or {@code text} if no replacement - * has been applied. + * @param buffer The text to scan for Unicode characters to replace by ASCII characters. + * @throws NullArgumentException If the given {@code buffer} is null. + * + * @see CharSequences#toASCII(CharSequence) */ - public static CharSequence toASCII(CharSequence text) { + public static void toASCII(final StringBuilder buffer) { + ArgumentChecks.ensureNonNull("buffer", buffer); + toASCII(buffer, buffer); + } + + /** + * Implementation of the public {@code toASCII} methods. + */ + static CharSequence toASCII(CharSequence text, StringBuilder buffer) { if (text != null) { - StringBuilder buffer = null; final int length = text.length(); for (int i=0; i= 0 && r - *

  • Invoke {@link #camelCaseToWords(CharSequence, boolean)}, which separate the words - * on the basis of character case. For example {@code "transferFunctionType"} become - * "transfer function type". This works fine for ISO 19115 identifiers.

  • - * - *
  • Next replace all occurrence of {@code '_'} by spaces in order to take in account - * an other common naming convention, which uses {@code '_'} as a word separator. This - * convention is used by NetCDF attributes like {@code "project_name"}.

  • - * - *
  • Finally ensure that the first character is upper-case.

  • - * - * - * {@section Exception to the above rules} - * If the given identifier contains only upper-case letters, digits and the {@code '_'} - * character, then the identifier is returned "as is" except for the {@code '_'} characters - * which are replaced by {@code '-'}. This work well for identifiers like {@code "UTF-8"} or - * {@code "ISO-LATIN-1"} for example. - *

    - * Note that those heuristic rules may be modified in future SIS versions, - * depending on the practical experience gained. - * - * @param identifier An identifier with no space, words begin with an upper-case character, - * or {@code null}. - * @return The identifier with spaces inserted after what looks like words, or {@code null} - * if the given argument was null. - */ - public static String camelCaseToSentence(final CharSequence identifier) { - if (identifier == null) { - return null; - } - if (isCode(identifier)) { - return identifier.toString().replace('_', '-'); - } - final StringBuilder buffer = camelCaseToWords(identifier, true); - final int length = buffer.length(); - for (int i=0; iPixel Interleaved Sample Model" or "Pixel interleaved sample model" - * depending on the value of the {@code toLowerCase} argument. - *

    - * If {@code toLowerCase} is {@code false}, then this method inserts spaces but does not change - * the case of characters. If {@code toLowerCase} is {@code true}, then this method changes - * {@linkplain Character#toLowerCase(int) to lower case} the first character after each spaces - * inserted by this method (note that this intentionally exclude the very first character in - * the given string), except if the second character {@linkplain Character#isUpperCase(int) - * is upper case}, in which case the words is assumed an acronym. - *

    - * The given string is usually a programmatic identifier like a class name or a method name. - * - * @param identifier An identifier with no space, words begin with an upper-case character. - * @param toLowerCase {@code true} for changing the first character of words to lower case, - * except for the first word and acronyms. - * @return The identifier with spaces inserted after what looks like words, returned - * as a {@link StringBuilder} in order to allow modifications by the caller. - * @throws NullPointerException if the {@code identifier} argument is null. - */ - public static StringBuilder camelCaseToWords(final CharSequence identifier, final boolean toLowerCase) { - final int length = identifier.length(); - final StringBuilder buffer = new StringBuilder(length + 8); - final int lastIndex = (length != 0) ? length - charCount(codePointBefore(identifier, length)) : 0; - int last = 0; - for (int i=1; i<=length;) { - final int cp; - final boolean doAppend; - if (i == length) { - cp = 0; - doAppend = true; - } else { - cp = codePointAt(identifier, i); - doAppend = Character.isUpperCase(cp) && isLowerCase(codePointBefore(identifier, i)); - } - if (doAppend) { - final int pos = buffer.length(); - buffer.append(identifier, last, i).append(' '); - if (toLowerCase && pos!=0 && last - * Examples: given {@code "northEast"}, this method returns {@code "NE"}. - * Given {@code "Open Geospatial Consortium"}, this method returns {@code "OGC"}. - * - * @param text The text for which to create an acronym, or {@code null}. - * @return The acronym, or {@code null} if the given text was null. - */ - public static String camelCaseToAcronym(String text) { - if (text != null && !isUpperCase(text = text.trim())) { - final int length = text.length(); - final StringBuilder buffer = new StringBuilder(8); // Acronyms are usually short. - boolean wantChar = true; - for (int i=0; i - * Example: given the string {@code "Open Geospatial Consortium"}, the following - * strings are recognized as acronyms: {@code "OGC"}, {@code "ogc"}, {@code "O.G.C."}, - * {@code "OpGeoCon"}. - * - * @param acronym A possible acronym of the sequence of words. - * @param words The sequence of words. - * @return {@code true} if the first string is an acronym of the second one. - * @throws NullPointerException if any of the arguments is null. - */ - public static boolean isAcronymForWords(final CharSequence acronym, final CharSequence words) { - final int lgc = words.length(); - final int lga = acronym.length(); - int ic=0, ia=0; - int ca, cc; - do { - if (ia >= lga) return false; - ca = codePointAt(acronym, ia); - ia += charCount(ca); - } while (!isLetterOrDigit(ca)); - do { - if (ic >= lgc) return false; - cc = codePointAt(words, ic); - ic += charCount(cc); - } - while (!isLetterOrDigit(cc)); - if (toUpperCase(ca) != toUpperCase(cc)) { - // The first letter must match. - return false; - } -cmp: while (ia < lga) { - if (ic >= lgc) { - // There is more letters in the acronym than in the complete name. - return false; - } - ca = codePointAt(acronym, ia); ia += charCount(ca); - cc = codePointAt(words, ic); ic += charCount(cc); - if (isLetterOrDigit(ca)) { - if (toUpperCase(ca) == toUpperCase(cc)) { - // Acronym letter matches the letter from the complete name. - // Continue the comparison with next letter of both strings. - continue; - } - // Will search for the next word after the 'else' block. - } else do { - if (ia >= lga) break cmp; - ca = codePointAt(acronym, ia); - ia += charCount(ca); - } while (!isLetterOrDigit(ca)); - /* - * At this point, 'ca' is the next acronym letter to compare and we - * need to search for the next word in the complete name. We first - * skip remaining letters, then we skip non-letter characters. - */ - boolean skipLetters = true; - do while (isLetterOrDigit(cc) == skipLetters) { - if (ic >= lgc) { - return false; - } - cc = codePointAt(words, ic); - ic += charCount(cc); - } while ((skipLetters = !skipLetters) == false); - // Now that we are aligned on a new word, the first letter must match. - if (toUpperCase(ca) != toUpperCase(cc)) { - return false; - } - } - /* - * Now that we have processed all acronym letters, the complete name can not have - * any additional word. We can only finish the current word and skip trailing non- - * letter characters. - */ - boolean skipLetters = true; - do { - do { - if (ic >= lgc) return true; - cc = codePointAt(words, ic); - ic += charCount(cc); - } while (isLetterOrDigit(cc) == skipLetters); - } while ((skipLetters = !skipLetters) == false); - return false; - } - - /** - * Returns {@code true} if the given string contains only upper case letters or digits. - * A few punctuation characters like {@code '_'} and {@code '.'} are also accepted. - *

    - * This method is used for identifying character strings that are likely to be code - * like {@code "UTF-8"} or {@code "ISO-LATIN-1"}. - * - * @see #isJavaIdentifier(CharSequence) - */ - private static boolean isCode(final CharSequence identifier) { - for (int i=identifier.length(); --i>=0;) { - final char c = identifier.charAt(i); - // No need to use the code point API here, since the conditions - // below are requiring the characters to be in the basic plane. - if (!((c >= 'A' && c <= 'Z') || (c >= '-' && c <= ':') || c == '_')) { - return false; - } - } - return true; - } - - /** - * 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. - */ - 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; - } - - /** - * Returns {@code true} if the given code points are equal, ignoring case. - * This method implements the same comparison algorithm than String#equalsIgnoreCase(String). - *

    - * This method does not verify if {@code c1 == c2}. This check should have been done - * by the caller, since the caller code is a more optimal place for this check. - */ - private static boolean equalsIgnoreCase(int c1, int c2) { - c1 = toUpperCase(c1); - c2 = toUpperCase(c2); - if (c1 == c2) { - return true; - } - // Need this check for Georgian alphabet. - return toLowerCase(c1) == toLowerCase(c2); - } - - /** - * Returns {@code true} if the two given strings are equal, ignoring case. - * This method is similar to {@link String#equalsIgnoreCase(String)}, except - * it works on arbitrary character sequences and compares code points - * instead than characters. - * - * @param s1 The first string to compare. - * @param s2 The second string to compare. - * @return {@code true} if the two given strings are equal, ignoring case. - * @throws NullPointerException if any of the arguments is null. - * - * @see String#equalsIgnoreCase(String) - */ - public static boolean equalsIgnoreCase(final CharSequence s1, final CharSequence s2) { - final int lg1 = s1.length(); - final int lg2 = s2.length(); - int i1 = 0, i2 = 0; - while (i1 string.length()) { - return false; - } - for (int i=0; i - * Let define c as the first non-blank character located at an index equals or - * greater than the given offset. Then the characters that are considered of the same type - * are: - *

    - *

      - *
    • If c is a - * {@linkplain Character#isJavaIdentifierStart(int) Java identifier start}, - * then any following character that are - * {@linkplain Character#isJavaIdentifierPart(int) Java identifier part}.
    • - *
    • Otherwise any character for which {@link Character#getType(int)} returns - * the same value than for c.
    • - *
    - * - * @param text The text for which to get the token. - * @param offset Index of the fist character to consider in the given text. - * @return A sub-sequence of {@code text} starting at the given offset, or an empty string - * if there is no non-blank character at or after the given offset. - * @throws NullPointerException if the {@code text} argument is null. - */ - public static CharSequence token(final CharSequence text, int offset) { - final int length = text.length(); - int upper = offset; - /* - * Skip whitespaces. At the end of this loop, - * 'c' will be the first non-blank character. - */ - int c; - do { - if (upper >= length) return ""; - c = codePointAt(text, upper); - offset = upper; - upper += charCount(c); - } - while (isWhitespace(c)); - /* - * Advance over all characters "of the same type". - */ - if (isJavaIdentifierStart(c)) { - while (upper= lgs) { - return false; - } - final int cs = codePointAt(sequence, is); - final int cp = codePointAt(prefix, ip); - if (cs != cp && (!ignoreCase || !equalsIgnoreCase(cs, cp))) { - return false; - } - is += charCount(cs); - ip += charCount(cp); - } - return true; - } - - /** - * Returns {@code true} if the given character sequence ends with the given suffix. - * - * @param sequence The sequence to test. - * @param suffix The expected suffix. - * @param ignoreCase {@code true} if the case should be ignored. - * @return {@code true} if the given sequence ends with the given suffix. - * @throws NullPointerException if any of the arguments is null. - */ - public static boolean endsWith(final CharSequence sequence, final CharSequence suffix, final boolean ignoreCase) { - int is = sequence.length(); - int ip = suffix .length(); - while (ip > 0) { - if (is <= 0) { - return false; - } - final int cs = codePointBefore(sequence, is); - final int cp = codePointBefore(suffix, ip); - if (cs != cp && (!ignoreCase || !equalsIgnoreCase(cs, cp))) { - return false; - } - is -= charCount(cs); - ip -= charCount(cp); - } - return true; - } - - /** - * Returns the index of the first character after the given number of lines. - * This method counts the number of occurrence of {@code '\n'}, {@code '\r'} - * or {@code "\r\n"} starting from the given position. When {@code numToSkip} - * occurrences have been found, the index of the first character after the last - * occurrence is returned. - * - * @param string The string in which to skip a determined amount of lines. - * @param numToSkip The number of lines to skip. Can be positive, zero or negative. - * @param startAt Index at which to start the search. - * @return Index of the first character after the last skipped line. - * @throws NullPointerException if the {@code string} argument is null. - */ - public static int skipLines(final CharSequence string, int numToSkip, int startAt) { - final int length = string.length(); - /* - * Go backward if the number of lines is negative. - * No need to use the codePoint API because we are - * looking only for '\r' and '\n' characters. - */ - if (numToSkip < 0) { - do { - char c; - do { - if (startAt == 0) { - return startAt; - } - c = string.charAt(--startAt); - if (c == '\n') { - if (startAt != 0 && string.charAt(startAt - 1) == '\r') { - --startAt; - } - break; - } - } while (c != '\r'); - } while (++numToSkip != 0); - numToSkip = 1; // For skipping the "end of line" characters. - } - /* - * Skips forward the given amount of lines. - */ - while (--numToSkip >= 0) { - char c; - do { - if (startAt >= length) { - return startAt; - } - c = string.charAt(startAt++); - if (c == '\r') { - if (startAt != length && string.charAt(startAt) == '\n') { - startAt++; - } - break; - } - } while (c != '\n'); - } - return startAt; - } - - /** - * Returns a {@link String} instance for each line found in a multi-lines string. Each element - * in the returned array will be a single line. If the given text is already a single line, - * then this method returns a singleton containing only the given text. - *

    - * The converse of this method is {@link #formatList(Iterable, String)}. - * - * {@note This method has been designed in a time when String.substring(int,int) - * was cheap, because it shared the same internal char[] array than the original - * array. However as of JDK8, the String implementation changed and now copies - * the data. The pertinence of this method may need to be re-evaluated.} - * - * @param text The multi-line text from which to get the individual lines. - * @return The lines in the text, or {@code null} if the given text was null. - */ - public static String[] getLinesFromMultilines(final String text) { - if (text == null) { - return null; - } - /* - * This method is implemented on top of String.indexOf(int,int), which is the - * fatest method available while taking care of the complexity of code points. - */ - int lf = text.indexOf('\n'); - int cr = text.indexOf('\r'); - if (lf < 0 && cr < 0) { - return new String[] { - text - }; - } - int count = 0; - String[] splitted = new String[8]; - int last = 0; - boolean hasMore; - do { - int skip = 1; - final int splitAt; - if (cr < 0) { - // There is no "\r" character in the whole text, only "\n". - splitAt = lf; - hasMore = (lf = text.indexOf('\n', lf+1)) >= 0; - } else if (lf < 0) { - // There is no "\n" character in the whole text, only "\r". - splitAt = cr; - hasMore = (cr = text.indexOf('\r', cr+1)) >= 0; - } else if (lf < cr) { - // There is both "\n" and "\r" characters with "\n" first. - splitAt = lf; - hasMore = true; - lf = text.indexOf('\n', lf+1); - } else { - // There is both "\r" and "\n" characters with "\r" first. - // We need special care for the "\r\n" sequence. - splitAt = cr; - if (lf == ++cr) { - cr = text.indexOf('\r', cr+1); - lf = text.indexOf('\n', lf+1); - hasMore = (cr >= 0 || lf >= 0); - skip = 2; - } else { - cr = text.indexOf('\r', cr+1); - hasMore = true; // Because there is lf. - } - } - if (count >= splitted.length) { - splitted = copyOf(splitted, count*2); - } - splitted[count++] = text.substring(last, splitAt); - last = splitAt + skip; - } while (hasMore); - /* - * Add the remaining string and we are done. - */ - if (count >= splitted.length) { - splitted = copyOf(splitted, count+1); - } - splitted[count++] = text.substring(last); - return resize(splitted, count); - } } Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java?rev=1389286&r1=1389285&r2=1389286&view=diff ============================================================================== --- sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java (original) +++ sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java Mon Sep 24 10:48:37 2012 @@ -16,6 +16,7 @@ */ package org.apache.sis.util; +import java.util.Arrays; import org.junit.*; import static org.junit.Assert.*; import static org.apache.sis.util.CharSequences.*; @@ -39,34 +40,85 @@ public final strictfp class CharSequence assertEquals("", spaces(0)); assertEquals(" ", spaces(1)); assertEquals(" ", spaces(8)); + assertEquals("", spaces(-2)); } /** - * Tests {@link CharSequences#count(String, String)} and its variants. + * Tests {@link CharSequences#length(CharSequence)}. + */ + @Test + public void testLength() { + assertEquals(3, length("ABC")); + assertEquals(0, length(null)); + } + + /** + * Tests {@link CharSequences#count(CharSequence, String)} and its variants. */ @Test public void testCount() { assertEquals(0, count("An ordinary sentence.", '-')); assertEquals(4, count("- this one has -dashs--", '-')); assertEquals(2, count("An ordinary sentence.", "en")); + assertEquals(0, count(new StringBuilder("An ordinary sentence."), '-')); + assertEquals(4, count(new StringBuilder("- this one has -dashs--"), '-')); + assertEquals(2, count(new StringBuilder("An ordinary sentence."), "en")); } /** - * Tests {@link CharSequences#split(String, char)}. + * Tests {@link CharSequences#split(CharSequence, char)}. */ @Test public void testSplit() { - assertArrayEquals(new String[] {"lundi", "mardi", "mercredi"}, - CharSequences.split("lundi , mardi,mercredi ", ',')); + assertArrayEquals(new String[] {"lundi", "mardi", "", "mercredi"}, split("lundi , mardi,,mercredi ", ',')); + } + + /** + * Tests {@link CharSequences#parseDoubles(CharSequence, char)}. + */ + @Test + public void testParseDoubles() { + assertArrayEquals(new double[] {5, 1.5, Double.NaN, -8}, parseDoubles("5 , 1.5,, -8 ", ','), 0.0); + } + + /** + * Tests {@link CharSequences#parseFloats(CharSequence, char)}. + */ + @Test + public void testParseFloats() { + assertArrayEquals(new float[] {5, 1.5f, Float.NaN, -8}, parseFloats("5 , 1.5,, -8 ", ','), 0f); + } + + /** + * Tests {@link CharSequences#parseLongs(CharSequence, char)}. + */ + @Test + public void testParseLongs() { + assertArrayEquals(new long[] {5, 2, -8}, parseLongs("5 , 2, -8 ", ',', 10)); + } + + /** + * Tests {@link CharSequences#parseInts(CharSequence, char)}. + */ + @Test + public void testParseInts() { + assertArrayEquals(new int[] {5, 2, -8}, parseInts("5 , 2, -8 ", ',', 10)); } /** - * Tests {@link CharSequences#parseFloats(String, char)}. + * Tests {@link CharSequences#parseShorts(CharSequence, char)}. */ @Test - public void testFloats() { - assertArrayEquals(new float[] {5, 1.5f, Float.NaN, -8}, - CharSequences.parseFloats("5 , 1.5,, -8 ", ','), 0f); + public void testParseShorts() { + assertArrayEquals(new short[] {5, 2, -8}, parseShorts("5 , 2, -8 ", ',', 10)); + } + + /** + * Tests {@link CharSequences#parseBytes(CharSequence, char)}. + */ + @Test + public void testParseBytes() { + assertArrayEquals(new byte[] {5, 2, -8}, parseBytes("5 , 2, -8 ", ',', 10)); } /** @@ -93,51 +145,24 @@ public final strictfp class CharSequence } /** - * Tests the {@link CharSequences#replace(StringBuilder, String, String)} method. - */ - @Test - public void testReplace() { - final StringBuilder buffer = new StringBuilder("One two three two one"); - replace(buffer, "two", "zero"); - assertEquals("One zero three zero one", buffer.toString()); - replace(buffer, "zero", "ten"); - assertEquals("One ten three ten one", buffer.toString()); - } - - /** - * Tests the {@link CharSequences#replace(StringBuilder, int, int, char[])} method. - */ - @Test - public void testReplaceChars() { - final StringBuilder buffer = new StringBuilder("ABCD1234EFGH"); - replace(buffer, 4, 8, new char[] {'5','6','7','8'}); - assertEquals("ABCD5678EFGH", buffer.toString()); - replace(buffer, 4, 6, new char[] {'1','2','3','4'}); - assertEquals("ABCD123478EFGH", buffer.toString()); - replace(buffer, 8, 10, new char[] {'a','b','c','d'}); - assertEquals("ABCD1234abcdEFGH", buffer.toString()); - } - - /** - * Tests the {@link CharSequences#remove(StringBuilder, String)} method. + * Tests the {@link CharSequences#formatList(Iterable, String)} method. */ @Test - public void testRemove() { - final StringBuilder buffer = new StringBuilder("EPSG.6.7"); - remove(buffer, "."); - assertEquals("EPSG67", buffer.toString()); + public void testFormatList() { + assertEquals("4, 8, 12, 9", formatList(Arrays.asList(4, 8, 12, 9), ", ")); + assertSame ("singleton", formatList(Arrays.asList("singleton"), ", ")); } /** - * Tests the {@link CharSequences#trim(String)} method. + * Tests the {@link CharSequences#trimWhitespaces(CharSequence)} method. */ @Test - public void testTrim() { - assertEquals("A text.", trim(" A text. ")); + public void testTrimWhitespaces() { + assertEquals("A text.", trimWhitespaces(" A text. ")); } /** - * Tests the {@link CharSequences#trimFractionalPart(String)} method. + * Tests the {@link CharSequences#trimFractionalPart(CharSequence)} method. */ @Test public void testTrimFractionalPart() { @@ -177,35 +202,16 @@ public final strictfp class CharSequence } /** - * Tests the {@link CharSequences#getLinesFromMultilines(String)} method. - */ - @Test - public void testGetLinesFromMultilines() { - final String[] splitted = getLinesFromMultilines("\nOne\r\nTwo\rThree\rFour\nFive\n\rSix\n"); - assertArrayEquals(new String[] { - "", - "One", - "Two", - "Three", - "Four", - "Five", - "", - "Six", - "" - }, splitted); - } - - /** * Tests the {@link CharSequences#camelCaseToAcronym(String)} method. */ @Test public void testCamelCaseToAcronym() { - assertEquals("OGC", camelCaseToAcronym("OGC")); - assertEquals("OGC", camelCaseToAcronym("Open Geospatial Consortium")); - assertEquals("E", camelCaseToAcronym("East")); - assertEquals("NE", camelCaseToAcronym("North-East")); - assertEquals("NE", camelCaseToAcronym("NORTH_EAST")); - assertEquals("NE", camelCaseToAcronym("northEast")); + assertEquals("OGC", camelCaseToAcronym("OGC").toString()); + assertEquals("OGC", camelCaseToAcronym("Open Geospatial Consortium").toString()); + assertEquals("E", camelCaseToAcronym("East").toString()); + assertEquals("NE", camelCaseToAcronym("North-East").toString()); + assertEquals("NE", camelCaseToAcronym("NORTH_EAST").toString()); + assertEquals("NE", camelCaseToAcronym("northEast").toString()); } /** @@ -260,4 +266,23 @@ public final strictfp class CharSequence */ assertFalse(isAcronymForWords("coordoperation", "[Coordinate_Operation Method]")); } + + /** + * Tests the {@link CharSequences#getLinesFromMultilines(String)} method. + */ + @Test + public void testGetLinesFromMultilines() { + final CharSequence[] splitted = getLinesFromMultilines("\nOne\r\nTwo\rThree\rFour\nFive\n\rSix\n"); + assertArrayEquals(new String[] { + "", + "One", + "Two", + "Three", + "Four", + "Five", + "", + "Six", + "" + }, splitted); + } } Copied: sis/trunk/sis-utility/src/test/java/org/apache/sis/util/StringBuildersTest.java (from r1388393, sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java) URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/util/StringBuildersTest.java?p2=sis/trunk/sis-utility/src/test/java/org/apache/sis/util/StringBuildersTest.java&p1=sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java&r1=1388393&r2=1389286&rev=1389286&view=diff ============================================================================== --- sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java (original) +++ sis/trunk/sis-utility/src/test/java/org/apache/sis/util/StringBuildersTest.java Mon Sep 24 10:48:37 2012 @@ -18,11 +18,11 @@ package org.apache.sis.util; import org.junit.*; import static org.junit.Assert.*; -import static org.apache.sis.util.CharSequences.*; +import static org.apache.sis.util.StringBuilders.*; /** - * Tests {@link CharSequences} methods. + * Tests {@link StringBuilders} methods. * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) @@ -30,70 +30,9 @@ import static org.apache.sis.util.CharSe * @version 0.3 * @module */ -public final strictfp class CharSequencesTest { +public final strictfp class StringBuildersTest { /** - * Tests {@link CharSequences#spaces(int)}. - */ - @Test - public void testSpaces() { - assertEquals("", spaces(0)); - assertEquals(" ", spaces(1)); - assertEquals(" ", spaces(8)); - } - - /** - * Tests {@link CharSequences#count(String, String)} and its variants. - */ - @Test - public void testCount() { - assertEquals(0, count("An ordinary sentence.", '-')); - assertEquals(4, count("- this one has -dashs--", '-')); - assertEquals(2, count("An ordinary sentence.", "en")); - } - - /** - * Tests {@link CharSequences#split(String, char)}. - */ - @Test - public void testSplit() { - assertArrayEquals(new String[] {"lundi", "mardi", "mercredi"}, - CharSequences.split("lundi , mardi,mercredi ", ',')); - } - - /** - * Tests {@link CharSequences#parseFloats(String, char)}. - */ - @Test - public void testFloats() { - assertArrayEquals(new float[] {5, 1.5f, Float.NaN, -8}, - CharSequences.parseFloats("5 , 1.5,, -8 ", ','), 0f); - } - - /** - * Tests the {@link CharSequences#indexOf(CharSequence, CharSequence, int)} method. - * We test four time with different kind of character sequences. - */ - @Test - public void testIndexOf() { - for (int i=0; i<3; i++) { - CharSequence string = "An ordinary sentence."; - switch (i) { - case 0: /* Test directly on the String instance. */ break; - case 1: string = new StringBuilder ((String) string); break; - case 2: string = new StringBuffer ((String) string); break; -// TODO case 3: string = new SimpleInternationalString((String) string); break; - default: throw new AssertionError(i); - } - assertEquals(-1, indexOf(string, "dummy", 0)); - assertEquals( 0, indexOf(string, "An", 0)); - assertEquals(-1, indexOf(string, "An", 1)); - assertEquals(12, indexOf(string, "sentence.", 0)); - assertEquals(-1, indexOf(string, "sentence;", 0)); - } - } - - /** - * Tests the {@link CharSequences#replace(StringBuilder, String, String)} method. + * Tests the {@link StringBuilders#replace(StringBuilder, String, String)} method. */ @Test public void testReplace() { @@ -105,7 +44,17 @@ public final strictfp class CharSequence } /** - * Tests the {@link CharSequences#replace(StringBuilder, int, int, char[])} method. + * Tests the {@link StringBuilders#replace(StringBuilder, char, char)} method. + */ + @Test + public void testReplaceChar() { + final StringBuilder buffer = new StringBuilder("ABCDEFBCD"); + replace(buffer, 'B', '*'); + assertEquals("A*CDEF*CD", buffer.toString()); + } + + /** + * Tests the {@link StringBuilders#replace(StringBuilder, int, int, char[])} method. */ @Test public void testReplaceChars() { @@ -119,7 +68,7 @@ public final strictfp class CharSequence } /** - * Tests the {@link CharSequences#remove(StringBuilder, String)} method. + * Tests the {@link StringBuilders#remove(StringBuilder, String)} method. */ @Test public void testRemove() { @@ -129,135 +78,25 @@ public final strictfp class CharSequence } /** - * Tests the {@link CharSequences#trim(String)} method. - */ - @Test - public void testTrim() { - assertEquals("A text.", trim(" A text. ")); - } - - /** - * Tests the {@link CharSequences#trimFractionalPart(String)} method. + * Tests the {@link StringBuilders#trimFractionalPart(StringBuilder)} method. */ @Test public void testTrimFractionalPart() { - assertEquals("4", trimFractionalPart("4")); - assertEquals("4", trimFractionalPart("4.")); - assertEquals("4", trimFractionalPart("4.0")); - assertEquals("4", trimFractionalPart("4.00")); - assertEquals("4.10", trimFractionalPart("4.10")); - } - - /** - * Tests the {@link CharSequences#token(CharSequence, int)} method. - */ - @Test - public void testToken() { - assertEquals("Id4", token("..Id4 56B..", 2)); - assertEquals("56", token("..Id4 56B..", 6)); + final StringBuilder buffer = new StringBuilder("4.10"); + trimFractionalPart(buffer); + assertEquals("4.10", buffer.toString()); + buffer.setCharAt(2, '0'); // Replace the '1' by '0'. + trimFractionalPart(buffer); + assertEquals("4", buffer.toString()); } /** - * Tests the {@link CharSequences#toASCII(CharSequence)} method. + * Tests the {@link StringBuilders#toASCII(CharSequence)} method. */ @Test public void testToASCII() { - final String metre = "metre"; - assertSame (metre, toASCII(metre)); - assertEquals(metre, toASCII("mètre").toString()); - } - - /** - * Tests the {@link CharSequences#camelCaseToWords(CharSequence, boolean)} method. - */ - @Test - public void testCamelCaseToWords() { - final CharSequence convert = camelCaseToWords("PixelInterleavedSampleModel", true); - assertEquals("Pixel interleaved sample model", convert.toString()); - } - - /** - * Tests the {@link CharSequences#getLinesFromMultilines(String)} method. - */ - @Test - public void testGetLinesFromMultilines() { - final String[] splitted = getLinesFromMultilines("\nOne\r\nTwo\rThree\rFour\nFive\n\rSix\n"); - assertArrayEquals(new String[] { - "", - "One", - "Two", - "Three", - "Four", - "Five", - "", - "Six", - "" - }, splitted); - } - - /** - * Tests the {@link CharSequences#camelCaseToAcronym(String)} method. - */ - @Test - public void testCamelCaseToAcronym() { - assertEquals("OGC", camelCaseToAcronym("OGC")); - assertEquals("OGC", camelCaseToAcronym("Open Geospatial Consortium")); - assertEquals("E", camelCaseToAcronym("East")); - assertEquals("NE", camelCaseToAcronym("North-East")); - assertEquals("NE", camelCaseToAcronym("NORTH_EAST")); - assertEquals("NE", camelCaseToAcronym("northEast")); - } - - /** - * Tests the {@link CharSequences#isAcronymForWords(CharSequence, CharSequence)} method. - */ - @Test - public void testIsAcronymForWords() { - /* - * Following should be accepted as acronyms... - */ - assertTrue(isAcronymForWords("OGC", "Open Geospatial Consortium")); - assertTrue(isAcronymForWords("O.G.C.", "Open Geospatial Consortium")); - assertTrue(isAcronymForWords("OpGeoCon", "Open Geospatial Consortium")); - assertTrue(isAcronymForWords("Open Geospatial Consortium", "Open Geospatial Consortium")); - assertTrue(isAcronymForWords("ogc", "Open Geospatial Consortium")); - /* - * Following should be rejected... - */ - assertFalse(isAcronymForWords("ORC", "Open Geospatial Consortium")); - assertFalse(isAcronymForWords("O.C.G.", "Open Geospatial Consortium")); - assertFalse(isAcronymForWords("OGC2", "Open Geospatial Consortium")); - assertFalse(isAcronymForWords("OG", "Open Geospatial Consortium")); - assertFalse(isAcronymForWords("GC", "Open Geospatial Consortium")); - /* - * Following are mapping of EPSG table names from MS-Access to ANSI SQL. - * All those items must be recognized as acroynms - this is requred by DirectEpsgFactory. - */ - assertTrue(isAcronymForWords("alias", "[Alias]")); - assertTrue(isAcronymForWords("area", "[Area]")); - assertTrue(isAcronymForWords("coordinateaxis", "[Coordinate Axis]")); - assertTrue(isAcronymForWords("coordinateaxisname", "[Coordinate Axis Name]")); - assertTrue(isAcronymForWords("coordoperation", "[Coordinate_Operation]")); - assertTrue(isAcronymForWords("coordoperationmethod", "[Coordinate_Operation Method]")); - assertTrue(isAcronymForWords("coordoperationparam", "[Coordinate_Operation Parameter]")); - assertTrue(isAcronymForWords("coordoperationparamusage", "[Coordinate_Operation Parameter Usage]")); - assertTrue(isAcronymForWords("coordoperationparamvalue", "[Coordinate_Operation Parameter Value]")); - assertTrue(isAcronymForWords("coordoperationpath", "[Coordinate_Operation Path]")); - assertTrue(isAcronymForWords("coordinatereferencesystem", "[Coordinate Reference System]")); - assertTrue(isAcronymForWords("coordinatesystem", "[Coordinate System]")); - assertTrue(isAcronymForWords("datum", "[Datum]")); - assertTrue(isAcronymForWords("ellipsoid", "[Ellipsoid]")); - assertTrue(isAcronymForWords("namingsystem", "[Naming System]")); - assertTrue(isAcronymForWords("primemeridian", "[Prime Meridian]")); - assertTrue(isAcronymForWords("supersession", "[Supersession]")); - assertTrue(isAcronymForWords("unitofmeasure", "[Unit of Measure]")); - assertTrue(isAcronymForWords("versionhistory", "[Version History]")); - assertTrue(isAcronymForWords("change", "[Change]")); - assertTrue(isAcronymForWords("deprecation", "[Deprecation]")); - /* - * It is important the the following is not recognized as an acronym, - * otherwise it leads to a confusion in DirectEpsgFactory. - */ - assertFalse(isAcronymForWords("coordoperation", "[Coordinate_Operation Method]")); + final StringBuilder metre = new StringBuilder("mètre"); + toASCII(metre); + assertEquals("metre", metre.toString()); } }