blob: e62ced82967ffbfe78e26265eb3eb634a04a34ed [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jens Lukowski/Innoopract - initial renaming/restructuring
*
*******************************************************************************/
package org.eclipse.wst.sse.core.utils;
import java.util.ArrayList;
import java.util.List;
import com.ibm.icu.util.StringTokenizer;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.wst.sse.core.internal.Logger;
public class StringUtils {
protected static final String AMPERSTAND = "&"; //$NON-NLS-1$
protected static final String AMPERSTAND_ENTITY = "&&;"; //$NON-NLS-1$
protected static final String CARRIAGE_RETURN = "\r"; //$NON-NLS-1$
protected static final String CARRIAGE_RETURN_ENTITY = "\\r"; //$NON-NLS-1$
protected static final String CR = "\r"; //$NON-NLS-1$
protected static final String CRLF = "\r\n"; //$NON-NLS-1$
protected static final String DELIMITERS = " \t\n\r\f"; //$NON-NLS-1$
protected static final String DOUBLE_QUOTE = "\""; //$NON-NLS-1$
protected static final char DOUBLE_QUOTE_CHAR = '\"'; //$NON-NLS-1$
protected static final String DOUBLE_QUOTE_ENTITY = """; //$NON-NLS-1$
protected static final String EQUAL_SIGN = "="; //$NON-NLS-1$
protected static final String EQUAL_SIGN_ENTITY = "="; //$NON-NLS-1$
private static final String FALSE = "false"; //$NON-NLS-1$
protected static final String GREATER_THAN = ">"; //$NON-NLS-1$
protected static final String GREATER_THAN_ENTITY = ">"; //$NON-NLS-1$
protected static final String LESS_THAN = "<"; //$NON-NLS-1$
protected static final String LESS_THAN_ENTITY = "&lt;"; //$NON-NLS-1$
protected static final String LF = "\n"; //$NON-NLS-1$
protected static final String LINE_FEED = "\n"; //$NON-NLS-1$
protected static final String LINE_FEED_ENTITY = "\\n"; //$NON-NLS-1$
protected static final String LINE_FEED_TAG = "<dl>"; //$NON-NLS-1$
protected static final String LINE_TAB = "\t"; //$NON-NLS-1$
protected static final String LINE_TAB_ENTITY = "\\t"; //$NON-NLS-1$
protected static final String LINE_TAB_TAG = "<dd>"; //$NON-NLS-1$
protected static final String SINGLE_QUOTE = "'"; //$NON-NLS-1$
protected static final char SINGLE_QUOTE_CHAR = '\''; //$NON-NLS-1$
protected static final String SINGLE_QUOTE_ENTITY = "&#039;"; //$NON-NLS-1$
protected static final String SPACE = " "; //$NON-NLS-1$
protected static final String SPACE_ENTITY = "&nbsp;"; //$NON-NLS-1$
private static final String TRUE = "true"; //$NON-NLS-1$
/**
* Append appendString to the end of aString only if aString does not end
* with the insertString.
*/
public static String appendIfNotEndWith(String aString, String appendString) {
if ((aString != null) && (appendString != null))
if (aString.endsWith(appendString))
return aString;
else
return aString + appendString;
else
return aString;
}
/**
* Breaks out space-separated words into an array of words. For example:
* <code>"no comment"</code> into an array <code>a[0]="no"</code> and
* <code>a[1]= "comment"</code>.
*
* @param value
* the string to be converted
* @return the list of words
*/
public static String[] asArray(String value) {
ArrayList list = new ArrayList();
StringTokenizer stok = new StringTokenizer(value);
while (stok.hasMoreTokens()) {
list.add(stok.nextToken());
}
String result[] = new String[list.size()];
list.toArray(result);
return result;
}
/**
* Breaks out delim-separated words into an array of words. For example:
* <code>"no comment"</code> into an array <code>a[0]="no"</code> and
* <code>a[1]= "comment"</code>.
*
* @param value
* the string to be converted
* @return the list of words
*/
public static String[] asArray(String value, String delim) {
return asArray(value, delim, false);
}
/**
* Breaks out delim-separated words into an array of words. For example:
* <code>"no comment"</code> into an array <code>a[0]="no"</code> and
* <code>a[1]= "comment"</code>.
*
* @param value
* the string to be converted
* @return the list of words
*/
public static String[] asArray(String value, String delim, boolean returnTokens) {
ArrayList list = new ArrayList();
StringTokenizer stok = new StringTokenizer(value, delim, returnTokens);
while (stok.hasMoreTokens()) {
list.add(stok.nextToken());
}
String result[] = new String[list.size()];
list.toArray(result);
return result;
}
/**
* Breaks out delim-separated words into an array of words. For example:
* <code>"abc,,def"</code> into an array <code>a[0]="abc"</code>,
* <code>a[1]=null</code>, and <code>a[2]= "def"</code> where "," is
* the delim.
*
* @param value
* the string to be converted
* @return the list of words
*/
public static String[] asFixedArray(String value, String delim) {
String array[] = asArray(value, delim, true);
int arrayLength = array.length;
boolean stringFound = false;
ArrayList list = new ArrayList();
for (int i = 0; i < arrayLength; i++) {
String token = array[i];
if (token.compareTo(delim) == 0) {
if (!stringFound)
list.add(null);
stringFound = false;
}
else {
list.add(token);
stringFound = true;
}
}
// add one more null if last token is the delim
if (!stringFound)
list.add(null);
String result[] = new String[list.size()];
list.toArray(result);
return result;
}
public static String chop(String source) {
return chop(source, "/"); //$NON-NLS-1$
}
public static String chop(String source, String delimiter) {
return source.substring(0, source.lastIndexOf(delimiter));
}
public static boolean contains(String[] arrayOfStrings, String needle, boolean caseSensitive) {
boolean result = false;
if (needle == null)
return false;
if (arrayOfStrings == null)
return false;
if (caseSensitive) {
for (int i = 0; i < arrayOfStrings.length; i++) {
if (needle.equals(arrayOfStrings[i])) {
result = true;
break;
}
}
}
else {
for (int i = 0; i < arrayOfStrings.length; i++) {
if (needle.equalsIgnoreCase(arrayOfStrings[i])) {
result = true;
break;
}
}
}
return result;
}
public static boolean containsLetters(String fullValue) {
if (fullValue == null || fullValue.length() == 0)
return false;
char[] chars = fullValue.toCharArray();
for (int i = 0; i < fullValue.length(); i++)
if (Character.isLetter(chars[i]))
return true;
return false;
}
public static boolean containsLineDelimiter(String aString) {
return indexOfLineDelimiter(aString) != -1;
}
public static String convertLineDelimiters(String allText, String lineDelimiterToUse) {
IDocument tempDoc = new Document(allText);
if (lineDelimiterToUse == null)
lineDelimiterToUse = System.getProperty("line.separator"); //$NON-NLS-1$
String newText = ""; //$NON-NLS-1$
int lineCount = tempDoc.getNumberOfLines();
for (int i = 0; i < lineCount; i++) {
try {
org.eclipse.jface.text.IRegion lineInfo = tempDoc.getLineInformation(i);
int lineStartOffset = lineInfo.getOffset();
int lineLength = lineInfo.getLength();
int lineEndOffset = lineStartOffset + lineLength;
newText += allText.substring(lineStartOffset, lineEndOffset);
if ((i < lineCount - 1) && (tempDoc.getLineDelimiter(i) != null))
newText += lineDelimiterToUse;
}
catch (BadLocationException e) {
// log for now, unless we find reason not to
Logger.log(Logger.INFO, e.getMessage());
}
}
return newText;
}
/**
* Replaces all instances of special HTML characters with the appropriate
* HTML entity equivalent. WARNING only use this method for strings that
* dont already have HTML-specific items such as tags and entities.
*
* @param String
* content String to convert
*
* @return String the converted string
* @see HTMLPrinter#convertToHTMLContent(String content)
*/
public static String convertToHTMLContent(String content) {
content = replace(content, AMPERSTAND, AMPERSTAND_ENTITY);
content = replace(content, LESS_THAN, LESS_THAN_ENTITY);
content = replace(content, GREATER_THAN, GREATER_THAN_ENTITY);
content = replace(content, LINE_FEED, LINE_FEED_TAG);
content = replace(content, LINE_TAB, LINE_TAB_TAG);
content = replace(content, SINGLE_QUOTE, SINGLE_QUOTE_ENTITY);
content = replace(content, DOUBLE_QUOTE, DOUBLE_QUOTE_ENTITY);
content = replace(content, SPACE + SPACE, SPACE_ENTITY + SPACE_ENTITY); // replacing
// every
// space
// would
// be
// too
// much
return content;
}
/**
* Converts a string into a form that will not conflict with saving it
* into an INI file
*/
public static String escape(String normalString) {
if (normalString == null)
return null;
StringBuffer escapedBuffer = new StringBuffer();
StringTokenizer toker = new StringTokenizer(normalString, EQUAL_SIGN + LINE_FEED + CARRIAGE_RETURN + LINE_TAB, true);
String chunk = null;
while (toker.hasMoreTokens()) {
chunk = toker.nextToken();
if (chunk.equals(EQUAL_SIGN)) {
escapedBuffer.append(EQUAL_SIGN_ENTITY);
}
else if (chunk.equals(LINE_FEED)) {
escapedBuffer.append(LINE_FEED_ENTITY);
}
else if (chunk.equals(CARRIAGE_RETURN)) {
escapedBuffer.append(CARRIAGE_RETURN_ENTITY);
}
else if (chunk.equals(LINE_TAB)) {
escapedBuffer.append(LINE_TAB_ENTITY);
}
else {
escapedBuffer.append(chunk);
}
}
return escapedBuffer.toString();
}
/**
* Returns the first line of the given text without a trailing delimiter
*
* @param text
* @return
*/
public static String firstLineOf(String text) {
if (text == null || text.length() < 1) {
return text;
}
IDocument doc = new Document(text);
try {
int lineNumber = doc.getLineOfOffset(0);
IRegion line = doc.getLineInformation(lineNumber);
return doc.get(line.getOffset(), line.getLength());
}
catch (BadLocationException e) {
// do nothing
}
return text;
}
public static int indexOfLastLineDelimiter(String aString) {
return indexOfLastLineDelimiter(aString, aString.length());
}
public static int indexOfLastLineDelimiter(String aString, int offset) {
int index = -1;
if (aString != null && aString.length() > 0) {
index = aString.lastIndexOf(CRLF, offset);
if (index == -1) {
index = aString.lastIndexOf(CR, offset);
if (index == -1)
index = aString.lastIndexOf(LF, offset);
}
}
return index;
}
public static int indexOfLineDelimiter(String aString) {
return indexOfLineDelimiter(aString, 0);
}
public static int indexOfLineDelimiter(String aString, int offset) {
int index = -1;
if (aString != null && aString.length() > 0) {
index = aString.indexOf(CRLF, offset);
if (index == -1) {
index = aString.indexOf(CR, offset);
if (index == -1)
index = aString.indexOf(LF, offset);
}
}
return index;
}
public static int indexOfNonblank(String aString) {
return indexOfNonblank(aString, 0);
}
public static int indexOfNonblank(String aString, int offset) {
int index = -1;
if (aString != null && aString.length() > 0) {
for (int i = offset; i < aString.length(); i++) {
if (DELIMITERS.indexOf(aString.substring(i, i + 1)) == -1) {
index = i;
break;
}
}
}
return index;
}
/**
* Insert insertString to the beginning of aString only if aString does
* not start with the insertString.
*/
public static String insertIfNotStartWith(String aString, String insertString) {
if ((aString != null) && (insertString != null))
if (aString.startsWith(insertString))
return aString;
else
return insertString + aString;
else
return aString;
}
public static boolean isQuoted(String string) {
if ((string == null) || (string.length() < 2))
return false;
int lastIndex = string.length() - 1;
char firstChar = string.charAt(0);
char lastChar = string.charAt(lastIndex);
return (((firstChar == SINGLE_QUOTE_CHAR) && (lastChar == SINGLE_QUOTE_CHAR)) || ((firstChar == DOUBLE_QUOTE_CHAR) && (lastChar == DOUBLE_QUOTE_CHAR)));
}
/**
* Unit tests.
*
* @param args
* java.lang.String[]
*/
public static void main(String[] args) {
// testPaste();
testStripNonLetterDigits();
}
/*
* Returns the merged form of both strings
*/
public static String merge(String newStart, String newEnd) {
String[] regions = overlapRegions(newStart, newEnd);
return regions[0] + regions[1] + regions[2];
}
public static int occurrencesOf(String searchString, char targetChar) {
int result = 0;
int len = searchString.length();
for (int i = 0; i < len; i++) {
if (targetChar == searchString.charAt(i))
result++;
}
return result;
}
/**
*
* @return java.lang.String[]
* @param start
* java.lang.String
* @param end
* java.lang.String
*
* Returns a 3 String array containing unique text from the start,
* duplicated text that overlaps the start and end, and the unique text
* from the end.
*/
private static String[] overlapRegions(String start, String end) {
String[] results = null;
if (start != null && end == null) {
results = new String[]{start, "", ""}; //$NON-NLS-2$//$NON-NLS-1$
}
else if (start == null && end != null) {
results = new String[]{"", "", end}; //$NON-NLS-2$//$NON-NLS-1$
}
else if (start == null && end == null) {
results = new String[]{"", "", ""}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
}
else if (start != null && end != null) {
int startLength = start.length();
int endLength = end.length();
if (startLength == 0 || endLength == 0) {
results = new String[]{"", "", ""}; //$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
}
else {
results = new String[3];
String testStart = ""; //$NON-NLS-1$
String testEnd = ""; //$NON-NLS-1$
int mergeLength = Math.min(startLength, endLength);
boolean finished = false;
while (mergeLength > 0 && !finished) {
testStart = start.substring(startLength - mergeLength);
testEnd = end.substring(0, mergeLength);
// case sensitive
if (testStart.equals(testEnd)) {
finished = true;
results[0] = start.substring(0, startLength - mergeLength);
results[1] = start.substring(startLength - mergeLength);
results[2] = end.substring(mergeLength);
}
mergeLength--;
}
if (!finished) {
results[0] = start;
results[1] = ""; //$NON-NLS-1$
results[2] = end;
}
}
}
return results;
}
/**
* Packs an array of Strings into a single comma delimited String.
*
* @param strings
* @return
* @todo Generated comment
*/
public static String pack(String[] strings) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < strings.length; i++) {
buf.append(StringUtils.replace(strings[i], ",", "&comma;")); //$NON-NLS-1$ //$NON-NLS-2$
if (i < strings.length - 1)
buf.append(","); //$NON-NLS-1$
}
return buf.toString();
}
/*
* Pastes the new text into the old at the start position, replacing text
* implied by length.
*/
public static String paste(String oldText, String newText, int start, int length) {
String result = null;
StringBuffer sb = new StringBuffer();
int startIndex = start;
int endIndex = start + length;
if (startIndex > oldText.length()) {
startIndex = oldText.length();
}
sb.append(oldText.substring(0, startIndex));
// null or empty new text accompliches a delete
if (newText != null) {
sb.append(newText);
}
if (endIndex < oldText.length()) {
sb.append(oldText.substring(endIndex));
}
result = sb.toString();
return result;
}
/**
* Replace matching literal portions of a string with another string
*/
public static String replace(String aString, String source, String target) {
if (aString == null)
return null;
String normalString = ""; //$NON-NLS-1$
int length = aString.length();
int position = 0;
int previous = 0;
int spacer = source.length();
while (position + spacer - 1 < length && aString.indexOf(source, position) > -1) {
position = aString.indexOf(source, previous);
normalString = normalString + aString.substring(previous, position) + target;
position += spacer;
previous = position;
}
normalString = normalString + aString.substring(position, aString.length());
return normalString;
}
/**
* Restore the entity references for markup delimiters in text where they
* have been replaced by the proper Unicode values through a DOM text
* parser.
*/
public static String restoreMarkers(String text) {
String content = text;
content = replace(content, AMPERSTAND, AMPERSTAND_ENTITY);
content = replace(content, LESS_THAN, LESS_THAN_ENTITY);
content = replace(content, GREATER_THAN, GREATER_THAN_ENTITY);
return content;
}
/**
* Removes extra whitespace characters and quotes
*/
public static String strip(String quotedString) {
if (quotedString == null || quotedString.length() == 0)
return quotedString;
String trimmed = quotedString.trim();
if (trimmed.length() < 2)
return quotedString;
char first = trimmed.charAt(0);
char nextToLast = trimmed.charAt(trimmed.length() - 2);
char last = trimmed.charAt(trimmed.length() - 1);
if ((first == '\"' && last == '\"' && nextToLast != '\\') || (first == '\'' && last == '\'' && nextToLast != '\\')) {
return trimmed.substring(1, trimmed.length() - 1);
}
return trimmed;
}
/**
* This method strips anything from the beginning and end of a string that
* is not a letter or digit. It is used by some encoding detectors to come
* up with the encoding name from illformed input (e.g in <?xml
* encoding="abc?> -- where final quote is left off, the '>' is returned
* with the rest of the attribute value 'abc').
*/
public static String stripNonLetterDigits(String fullValue) {
if (fullValue == null || fullValue.length() == 0)
return fullValue;
int fullValueLength = fullValue.length();
int firstPos = 0;
while (firstPos < fullValueLength && !Character.isLetterOrDigit(fullValue.charAt(firstPos))) {
firstPos++;
}
int lastPos = fullValueLength - 1;
while (lastPos > firstPos && !Character.isLetterOrDigit(fullValue.charAt(lastPos))) {
lastPos--;
}
String result = fullValue;
if (firstPos != 0 || lastPos != fullValueLength) {
result = fullValue.substring(firstPos, lastPos + 1);
}
return result;
}
/**
* Similar to strip, except quotes don't need to match such as "UTF' is
* still stripped of both quotes. (Plus, this one does not detect escaped
* quotes)
*/
public static String stripQuotes(String quotedValue) {
if (quotedValue == null)
return null;
// normally will never have leading or trailing blanks,
// but if it does, we'll do lenient interpretation
return stripQuotesLeaveInsideSpace(quotedValue).trim();
}
/**
* Like strip quotes, except leaves the start and end space inside the
* quotes
*
* @param quotedValue
* @return
*/
public static String stripQuotesLeaveInsideSpace(String quotedValue) {
if (quotedValue == null)
return null;
// nomally will never have leading or trailing blanks ... but just in
// case.
String result = quotedValue.trim();
int len = result.length();
if (len > 0) {
char firstChar = result.charAt(0);
if ((firstChar == SINGLE_QUOTE_CHAR) || (firstChar == DOUBLE_QUOTE_CHAR)) {
result = result.substring(1, len);
}
len = result.length();
if (len > 0) {
char lastChar = result.charAt(len - 1);
if ((lastChar == SINGLE_QUOTE_CHAR) || (lastChar == DOUBLE_QUOTE_CHAR)) {
result = result.substring(0, len - 1);
}
}
}
return result;
}
public static void testPaste() {
String testString = "The quick brown fox ..."; //$NON-NLS-1$
System.out.println(paste(testString, null, 4, 5));
System.out.println(paste(testString, null, 4, 6));
System.out.println(paste(testString, "", 4, 6)); //$NON-NLS-1$
System.out.println(paste(testString, "fast", 4, 6)); //$NON-NLS-1$
System.out.println(paste(testString, "fast ", 4, 6)); //$NON-NLS-1$
System.out.println(paste(testString, "But ", 0, 0)); //$NON-NLS-1$
System.out.println(paste("", "burp", 4, 6)); //$NON-NLS-2$//$NON-NLS-1$
}
public static void testStripNonLetterDigits() {
String testString = "abc"; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = ""; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = "\"abc\""; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = "\"ab-c1?"; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = "+++"; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = "abc="; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
testString = "abc "; //$NON-NLS-1$
System.out.println(testString + " -->" + stripNonLetterDigits(testString) + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
}
public static String toString(boolean booleanValue) {
if (booleanValue)
return TRUE;
else
return FALSE;
}
/**
* Remove "escaped" chars from a string.
*/
public static String unescape(String aString) {
if (aString == null)
return null;
String normalString = replace(aString, EQUAL_SIGN_ENTITY, EQUAL_SIGN);
normalString = replace(normalString, LINE_FEED_ENTITY, LINE_FEED);
normalString = replace(normalString, CARRIAGE_RETURN_ENTITY, CARRIAGE_RETURN);
normalString = replace(normalString, LINE_TAB_ENTITY, LINE_TAB);
return normalString;
}
public static String uniqueEndOf(String newStart, String newEnd) {
String[] regions = overlapRegions(newStart, newEnd);
return regions[2];
}
/**
* Unpacks a comma delimited String into an array of Strings
*
* @param s
* @return
* @todo Generated comment
*/
public static String[] unpack(String s) {
if (s == null)
return new String[0];
StringTokenizer toker = new StringTokenizer(s, ","); //$NON-NLS-1$
List list = new ArrayList();
while (toker.hasMoreTokens()) {
// since we're separating the values with ',', escape ',' in the
// values
list.add(StringUtils.replace(toker.nextToken(), "&comma;", ",").trim()); //$NON-NLS-1$ //$NON-NLS-2$
}
return (String[]) list.toArray(new String[0]);
}
/**
* StringUtils constructor comment.
*/
private StringUtils() {
super();
}
}