All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.intarsys.tools.string.StringTools Maven / Gradle / Ivy

There is a newer version: 4.11
Show newest version
/*
 * Copyright (c) 2007, intarsys consulting GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * - Neither the name of intarsys nor the names of its contributors may be used
 *   to endorse or promote products derived from this software without specific
 *   prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.intarsys.tools.string;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import de.intarsys.tools.file.FileTools;

/**
 * A tool class for the handling of strings.
 * 
 */
public class StringTools {
	public static final String CR = "\r"; //$NON-NLS-1$

	public static final String CRLF = "\r\n"; //$NON-NLS-1$

	public static final String DATEFORMAT_SIMPLE = "yy-MM-dd HH:mm:ss:SSSS"; //$NON-NLS-1$

	private static DateFormat DEFAULT_DATEFORMAT;

	/** An empty string constant */
	public static final String EMPTY = ""; //$NON-NLS-1$

	public static final String FORMAT_D = "d"; //$NON-NLS-1$

	public static final String FORMAT_F = "f"; //$NON-NLS-1$

	public static final String FORMAT_I = "i"; //$NON-NLS-1$

	public static final String FORMAT_P = "p"; //$NON-NLS-1$

	public static final String FORMAT_S = "s"; //$NON-NLS-1$

	public static final String LF = "\n"; //$NON-NLS-1$

	private static final String[] NO_ARGS = new String[0];

	/** An single space constant */
	public static final String SPACE = " "; //$NON-NLS-1$

	public static String breakForced(String value, int max, String breakPattern) {
		StringBuilder sb = new StringBuilder();
		if (value != null) {
			int begin = 0;
			int end = max;
			int length = value.length();
			int currentlength = length;
			while (currentlength > max) {
				sb.append(value.substring(begin, end));
				currentlength -= max;
				begin += max;
				end += max;
				if (currentlength > 0) {
					sb.append(breakPattern);
				}
			}
			if (end > length) {
				end = length;
			}
			sb.append(value.substring(begin, end));
		}
		return sb.toString();
	}

	/**
	 * Capitalizes the first letter of the text.
	 * 
	 * @param text
	 * @return a capitalized version of the text
	 */
	public static String capitalize(String text) {
		if (isEmpty(text)) {
			return EMPTY;
		}
		String first = text.substring(0, 1);
		first = first.toUpperCase();
		if (text.length() > 1) {
			return first + text.substring(1);
		} else {
			return first;
		}
	}

	/**
	 * clear character array content.
	 * 
	 * @param value
	 *            The value to be cleared
	 */
	static public void clear(char[] value) {
		if (value == null) {
			return;
		}
		Arrays.fill(value, '0');
	}

	/**
	 * Create a string representation and format value according to
	 * the instructions in format.
	 * 

* If value is null, the empty string is returned. *

*/ public static String format(Object value, String format) { if (value == null) { return EMPTY; } if (format.startsWith(FORMAT_S)) { return formatString(value, format.substring(1)); } if (format.startsWith(FORMAT_F)) { return formatFloat(value, format.substring(1)); } if (format.startsWith(FORMAT_I)) { return formatInteger(value, format.substring(1)); } if (format.startsWith(FORMAT_D)) { return formatDate(value, format.substring(1)); } if (format.startsWith(FORMAT_P)) { return formatPath(value, format.substring(1)); } // the default formattings if (value instanceof Date) { return new SimpleDateFormat(DATEFORMAT_SIMPLE).format(value); } if (value instanceof Long) { return Long.toString(((Long) value).longValue(), 32); } return value.toString(); } /** */ protected static String formatDate(Object value, String format) { Date date = null; if (value instanceof Date) { date = (Date) value; } else if (value instanceof Number) { date = new Date(((Number) value).longValue()); } else if (value instanceof String) { return (String) value; } else { return EMPTY; } if (StringTools.isEmpty(format)) { return formatDateDefault(date); } String pattern = parseArgsString(format); if (pattern == null) { char dateTime = '+'; char command = format.charAt(0); if ((command == 'd') || (command == 't')) { // date or time only dateTime = command; if (format.length() > 1) { command = format.charAt(1); } else { command = 'f'; } } if (dateTime == 'd') { if (command == 's') { DateFormat dateFormat = DateFormat .getDateInstance(DateFormat.SHORT); return dateFormat.format(date); } else if (command == 'm') { DateFormat dateFormat = DateFormat .getDateInstance(DateFormat.MEDIUM); return dateFormat.format(date); } else if (command == 'f') { DateFormat dateFormat = DateFormat .getDateInstance(DateFormat.FULL); return dateFormat.format(date); } } else if (dateTime == 't') { if (command == 's') { DateFormat dateFormat = DateFormat .getTimeInstance(DateFormat.SHORT); return dateFormat.format(date); } else if (command == 'm') { DateFormat dateFormat = DateFormat .getTimeInstance(DateFormat.MEDIUM); return dateFormat.format(date); } else if (command == 'f') { DateFormat dateFormat = DateFormat .getTimeInstance(DateFormat.FULL); return dateFormat.format(date); } } else { if (command == 's') { DateFormat dateFormat = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT); return dateFormat.format(date); } else if (command == 'm') { DateFormat dateFormat = DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.MEDIUM); return dateFormat.format(date); } else if (command == 'f') { DateFormat dateFormat = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL); return dateFormat.format(date); } } return formatDateDefault(date); } else { DateFormat tempFormat = new SimpleDateFormat(pattern); try { return tempFormat.format(date); } catch (Exception e) { return formatDateDefault(date); } } } /** * @param value */ protected static synchronized String formatDateDefault(Date date) { if (DEFAULT_DATEFORMAT == null) { DEFAULT_DATEFORMAT = new SimpleDateFormat("yyyy_MM_dd-HH_mm_ss_SSS"); //$NON-NLS-1$ } return DEFAULT_DATEFORMAT.format(date); } /** */ protected static String formatFloat(Object value, String format) { if (value == null) { return EMPTY; } double number = 0; if (value instanceof Number) { number = ((Number) value).doubleValue(); } else { if (value instanceof Date) { number = ((Date) value).getTime(); } else { if (value instanceof String) { try { number = Double.parseDouble((String) value); } catch (NumberFormatException e) { return (String) value; } } else { return value.toString(); } } } String pattern = parseArgsString(format); NumberFormat tempFormat = null; if (pattern == null) { tempFormat = NumberFormat.getNumberInstance(); } else { tempFormat = new DecimalFormat(pattern); } try { return tempFormat.format(number); } catch (Exception e) { return value.toString(); } } /** */ protected static String formatInteger(Object value, String format) { if (value == null) { return EMPTY; } char base = 'd'; if (format.length() > 1) { base = format.charAt(1); } long number = 0; if (value instanceof Number) { number = ((Number) value).longValue(); } else { if (value instanceof Date) { number = ((Date) value).getTime(); } else { if (value instanceof String) { try { number = Long.parseLong((String) value); } catch (NumberFormatException e) { return (String) value; } } else { return value.toString(); } } } try { if (base == 'b') { return Long.toString(number, 2); } if (base == 'o') { return Long.toString(number, 8); } if (base == 'd') { return Long.toString(number, 10); } if (base == 'x') { return Long.toString(number, 16); } return Long.toString(number, 10); } catch (Exception e) { return value.toString(); } } protected static String formatPath(Object value, String string) { return FileTools.trimPath(StringTools.safeString(value)); } protected static String formatString(Object value, String format) { String result = null; if (value == null) { result = EMPTY; } else { result = value.toString(); } String[] args = parseArgs(format); if (args.length == 0) { return result; } int rangeStart = 0; int rangeStop = result.length() - 1; try { rangeStart = Integer.parseInt(args[0]); if (args.length == 2) { rangeStop = Integer.parseInt(args[1]); } } catch (NumberFormatException e) { return result; } if (rangeStart < 0) { rangeStart = result.length() + rangeStart; } if (rangeStop < 0) { rangeStop = result.length() + rangeStop; } if (rangeStart < 0) { rangeStart = 0; } if (rangeStop < 0) { rangeStop = 0; } if (rangeStart > rangeStop) { rangeStop = rangeStart - 1; } if (rangeStart > result.length()) { rangeStart = result.length(); } if (rangeStop >= result.length()) { rangeStop = result.length() - 1; } return result.substring(rangeStart, rangeStop + 1); } public static String getCommonPrefix(String a, String b, boolean ignoreCase) { int lengthA = a.length(); int lengthB = b.length(); int max = lengthA > lengthB ? lengthB : lengthA; int i = 0; String tmpA; String tmpB; if (ignoreCase) { tmpA = a.toLowerCase(); tmpB = b.toLowerCase(); } else { tmpA = a; tmpB = b; } for (; i < max; i++) { if (tmpA.charAt(i) != tmpB.charAt(i)) { break; } } return a.substring(0, i); } /** * The first line of text (all characters up to the first occurrence of * either "\n" or "\r". * * @param text * The text where the first line is looked up. * * @return The first line of text */ public static String getFirstLine(String text) { if (text == null) { return EMPTY; } int indexCR = text.indexOf(CR); if (indexCR == -1) { indexCR = text.length(); } int indexLF = text.indexOf(LF); if (indexLF == -1) { indexLF = text.length(); } return text.substring(0, (indexCR > indexLF) ? indexLF : indexCR); } public static String getLeading(String value, int count) { if (value == null || value.length() <= count || count <= 3) { return value; } return value.substring(0, count - 3) + "..."; } /** * The number of lines in text. This is 1 + the number of "\n" * in text. * * @param text * The text where the lines are counted. * @return The number of lines in text. This is 1 + the number * of "\n" in text. */ public static int getLineCount(String text) { int count = 1; char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { if (chars[i] == '\n') { count++; } } return count; } public static String getTrailing(String value, int count) { if (value == null || value.length() <= count) { return value; } return "..." + value.substring(value.length() - count + 3, value.length()); } /** * true if value is "empty" in any respect. *

* This is the case when value == null, value has no characters or only * whitespace. * * @param value * The value to be inspected for emptyness. * @return true if value is "empty" in any * respect. */ static public boolean isEmpty(char[] value) { if ((value == null) || (value.length == 0)) { return true; } for (int i = 0; i < value.length; i++) { if (!Character.isWhitespace(value[i])) { return false; } } return true; } /** * true if value is "empty" in any respect. *

* This is the case when value == null, value has no characters or only * whitespace. * * @param value * The value to be inspected for emptyness. * @return true if value is "empty" in any * respect. */ static public boolean isEmpty(String value) { return (value == null) || (value.length() == 0) || (value.trim().length() == 0); } /** * true if value seems to be a numeric value. To * qualify only the first character is examined. value * qualifies as numeric if the first character is a digit, a "+", a "-" or a * ".". * * @param value * @return true if value seems to be numeric. */ public static boolean isNumeric(String value) { if (value == null || value.length() == 0) { return false; } char c = value.charAt(0); return Character.isDigit(c) || c == '-' || c == '+' || c == '.'; } /** * Joins a List of Strings to a single one. All elements are separated by * the separator. * * @param elements * List of Strings * @param separator * a String used as a separator between two elements, e.g. "\n" * for a new line. May be null. * @return the joined string */ public static String join(List elements, String separator) { return join(elements.toArray(new String[0]), separator); } /** * Joins an array of Strings to a single one. All elements are separated by * the separator. * * @param elements * array of Strings * @param separator * a String used as a separator between two elements, e.g. "\n" * for a new line. May be null. * @return the joined string */ public static String join(String[] elements, String separator) { int last = elements.length - 1; if (last == -1) { return EMPTY; } if (last == 0) { return elements[0]; } StringBuilder buffer = new StringBuilder(); for (int i = 0; i < last; i++) { buffer.append(elements[i]); if (separator != null) { buffer.append(separator); } } buffer.append(elements[last]); return buffer.toString(); } public static String padLeft(String value, int count) { if (value == null || value.length() >= count) { return value; } StringBuilder sb = new StringBuilder(); for (int i = count - value.length(); i > 0; i--) { sb.append(" "); } sb.append(value); return sb.toString(); } public static String padRight(String value, int count) { if (value == null || value.length() >= count) { return value; } StringBuilder sb = new StringBuilder(); sb.append(value); for (int i = count - value.length(); i > 0; i--) { sb.append(" "); } return sb.toString(); } protected static String[] parseArgs(String string) { String tempArgs = parseArgsString(string); if (tempArgs == null) { return NO_ARGS; } return tempArgs.split(","); } protected static String parseArgsString(String string) { int open = string.indexOf('('); int close = string.indexOf(')'); if ((open == -1) || (close == -1) || (open > close)) { return null; } return string.substring(open + 1, close); } /** * Parse a commandline string with the default escape character. * * @param line * The commandline string. * @return The array of string tokens in the commandline string. */ static public String[] parseCommandline(String line) { return parseCommandline(line, '\\'); } /** * Parse a commandline string. * * @param line * The commandline string. * @return The array of string tokens in the commandline string. */ static public String[] parseCommandline(String line, char escape) { List result = new ArrayList(); StringBuilder sb = new StringBuilder(); boolean escaped = false; boolean quoted = false; boolean commented = false; for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); if (commented) { if (c == '\n') { commented = false; } continue; } if (escaped) { escaped = false; if (c != '"') { sb.append(escape); } sb.append(c); continue; } if (c == escape) { escaped = true; continue; } if (c == '"') { quoted = !quoted; continue; } if (!quoted && (c == '#')) { if (sb.length() > 0) { result.add(sb.toString()); sb.setLength(0); } commented = true; continue; } if (!quoted && Character.isWhitespace(c)) { if (sb.length() > 0) { result.add(sb.toString()); sb.setLength(0); } continue; } sb.append(c); } if (escaped) { sb.append(escape); } if (sb.length() > 0) { result.add(sb.toString()); sb.setLength(0); } return (String[]) result.toArray(new String[result.size()]); } /** * Create a new path from the concatenation of prefix and name. * * @param prefix * @param separator * @param name * @return The new path */ public static String pathAppend(String prefix, String separator, String name) { if (StringTools.isEmpty(prefix)) { return name; } else { return prefix + separator + name; } } static public String quote(String value) { StringBuilder sb = new StringBuilder(); sb.append('"'); char[] chars = value.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == '"') { sb.append('\\'); } else if (c == '\\') { sb.append('\\'); } sb.append(c); } sb.append('"'); return sb.toString(); } /** * Create a string representation of object that is guaranteed * not to fail in any case. * * @param object * The object to be printed. * @return Create a string representation of object that is * guaranteed not to fail in any case. */ public static String safeString(Object object) { try { return String.valueOf(object); } catch (RuntimeException e) { return ""; //$NON-NLS-1$ } } /** * Create a byte array from the string. This is simply a fast version of * getBytes, ignoring any encoding. *

* If you use this, you should be sure you will encounter valid ascii * characters only! * * @param value * @return A byte array created from value, ignoring high byte. */ static public byte[] toByteArray(String value) { byte[] result = new byte[value.length()]; value.getBytes(0, result.length, result, 0); return result; } /** * Convert value to camel case notation. *

* value is tokenized at non alphanumeric characters, separator characters * are ignored. all tokens are converted to lowercase and then for all * tokens except the first the first character is uppercased. *

* The implementation tries to detect if value is already a camel case * string and preserves it. * * @param value * @return value in camel case notation */ static public String toCamelCase(String value, String allowed) { StringTokenizer st = new StringTokenizer(value, allowed, true); StringBuilder sb = new StringBuilder(); while (st.hasMoreTokens()) { String element = st.nextToken(); if (allowed.indexOf(element) >= 0) { continue; } String delimiter = ""; if (st.hasMoreTokens()) { delimiter = st.nextToken(); } String[] tokens = element.split("[^a-zA-Z0-9]"); int length = tokens.length; if (length == 1) { String token = tokens[0]; if (token.length() > 0) { if (Character.isLowerCase(token.charAt(0))) { // assume already in camel case... sb.append(token); } else { sb.append(token.toLowerCase()); } } else { sb.append(token.toLowerCase()); } } else { for (int i = 0; i < length; i++) { String token = tokens[i]; if (token.length() > 0) { if (i == 0) { sb.append(Character.toLowerCase(token.charAt(0))); } else { sb.append(Character.toUpperCase(token.charAt(0))); } sb.append(token.substring(1).toLowerCase()); } } } sb.append(delimiter); } return sb.toString(); } /** * Create a string from the byte array. This is simply a fast version of new * String(), ignoring any encoding. *

* If you use this, you should be sure you will encounter valid ascii * characters only! * * @param value * @return A string created from the byte values in value. */ static public String toString(byte[] value) { return new String(value, 0); } /** * Create a string containing only the alphanumeric content of * value. * * @param value * The string to be trimmed. * @return A string containing only the alphanumeric content of * value. */ static public String trimAlphaNumeric(String value) { StringReader reader; StringWriter writer; char[] buffer; reader = new StringReader(value); buffer = new char[1]; writer = new StringWriter(); try { while (reader.read(buffer) != -1) { if (Character.isLetterOrDigit(buffer[0])) { writer.write(buffer); } } } catch (IOException ex) { // working in memory; ignore } return writer.toString(); } /** * Create a new string from value without leading whitespace. * * @param value * The string to be stripped. * * @return A copy of value with leading whitespace stripped. */ public static String trimLeft(String value) { int i = 0; int len = value.length(); while (i < len) { if (Character.isWhitespace(value.charAt(i))) { i++; continue; } break; } return value.substring(i); } /** * Create a new string from value without trailing whitespace. * * @param value * The string to be stripped. * * @return A copy of value with trailing whitespace stripped. */ public static String trimRight(String value) { int i = value.length() - 1; while (i >= 0) { if (Character.isWhitespace(value.charAt(i))) { i--; continue; } break; } return value.substring(0, i + 1); } static public String unquote(String value) throws IOException { char[] chars = value.toCharArray(); int i = 0; if (i == chars.length) { return ""; } char c = chars[i++]; if (c != '"') { // not quoted return value; } StringBuilder sb = new StringBuilder(); while (true) { if (i == chars.length) { throw new IOException("preliminary end of input"); } c = chars[i++]; if (c == '\\') { if (i == chars.length) { throw new IOException("preliminary end of input"); } c = chars[i++]; sb.append(c); continue; } if (c == '"') { if (i != chars.length) { throw new IOException("preliminary end of quoted string"); } break; } sb.append(c); } return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy