package PreD.utils;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.KeyStroke;
/**
*
* @Description Utility class to peform common String manipulation algorithms.
* @Author zhangzuoqiang
* @Date 2012-1-12
*/
public class StringUtils {
// Constants used by escapeHTMLTags
private static final char[] QUOTE_ENCODE = """.toCharArray();
private static final char[] AMP_ENCODE = "&".toCharArray();
private static final char[] LT_ENCODE = "<".toCharArray();
private static final char[] GT_ENCODE = ">".toCharArray();
// patterns for the email address checks
private static Pattern basicAddressPattern;
private static Pattern validUserPattern;
private static Pattern domainPattern;
private static Pattern ipDomainPattern;
private static Pattern tldPattern;
// prepare the patterns
static {
// constants used in the parsing of email addresses
String basicAddress = "^([\\w\\.-]+)@([\\w\\.-]+)$";
String specialChars = "\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
String validChars = "[^ \f\n\r\t" + specialChars + "]";
String atom = validChars + "+";
String quotedUser = "(\"[^\"]+\")";
String word = "(" + atom + "|" + quotedUser + ")";
String validUser = "^" + word + "(\\." + word + ")*$";
String domain = "^" + atom + "(\\." + atom + ")+$";
String ipDomain = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
// from http://www.icann.org/tlds/
String knownTLDs = "^\\.(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$";
basicAddressPattern = Pattern.compile(basicAddress,
Pattern.CASE_INSENSITIVE);
validUserPattern = Pattern.compile(validUser, Pattern.CASE_INSENSITIVE);
domainPattern = Pattern.compile(domain, Pattern.CASE_INSENSITIVE);
ipDomainPattern = Pattern.compile(ipDomain, Pattern.CASE_INSENSITIVE);
tldPattern = Pattern.compile(knownTLDs, Pattern.CASE_INSENSITIVE);
}
/**
* Replaces all instances of oldString with newString in string.
*
* @param string
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static String replace(String string, String oldString,
String newString) {
if (string == null) {
return null;
}
// If the newString is null or zero length, just return the string since
// there's nothing
// to replace.
if (newString == null) {
return string;
}
int i = 0;
// Make sure that oldString appears at least once before doing any
// processing.
if ((i = string.indexOf(oldString, i)) >= 0) {
// Use char []'s, as they are more efficient to deal with.
char[] string2 = string.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(string2.length);
buf.append(string2, 0, i).append(newString2);
i += oLength;
int j = i;
// Replace all remaining instances of oldString with newString.
while ((i = string.indexOf(oldString, i)) > 0) {
buf.append(string2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(string2, j, string2.length - j);
return buf.toString();
}
return string;
}
/**
* Replaces all instances of oldString with newString in line with the
* <p/>
* added feature that matches of newString in oldString ignore case.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static String replaceIgnoreCase(String line, String oldString,
String newString) {
if (line == null) {
return null;
}
String lcLine = line.toLowerCase();
String lcOldString = oldString.toLowerCase();
int i = 0;
if ((i = lcLine.indexOf(lcOldString, i)) >= 0) {
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = lcLine.indexOf(lcOldString, i)) > 0) {
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
return buf.toString();
}
return line;
}
/**
* Replaces all instances of oldString with newString in line with the
* <p/>
* added feature that matches of newString in oldString ignore case.
* <p/>
* The count paramater is set to the number of replaces performed.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @param count
* a value that will be updated with the number of replaces
* <p/>
* performed.
* @return a String will all instances of oldString replaced by newString
*/
public static String replaceIgnoreCase(String line, String oldString,
String newString, int[] count) {
if (line == null) {
return null;
}
String lcLine = line.toLowerCase();
String lcOldString = oldString.toLowerCase();
int i = 0;
if ((i = lcLine.indexOf(lcOldString, i)) >= 0) {
int counter = 1;
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = lcLine.indexOf(lcOldString, i)) > 0) {
counter++;
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
count[0] = counter;
return buf.toString();
}
return line;
}
/**
* Replaces all instances of oldString with newString in line.
* <p/>
* The count Integer is updated with number of replaces.
*
* @param line
* the String to search to perform replacements on
* @param oldString
* the String that should be replaced by newString
* @param newString
* the String that will replace all instances of oldString
* @param count
* Number of replaces.
* @return a String will all instances of oldString replaced by newString
*/
public static String replace(String line, String oldString,
String newString, int[] count) {
if (line == null) {
return null;
}
int i = 0;
if ((i = line.indexOf(oldString, i)) >= 0) {
int counter = 1;
char[] line2 = line.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i = line.indexOf(oldString, i)) > 0) {
counter++;
buf.append(line2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
count[0] = counter;
return buf.toString();
}
return line;
}
/**
* This method takes a string and strips out all tags except <br>
* tags while still leaving
* <p/>
* the tag body intact.
*
* @param in
* the text to be converted.
* @return the input string with all tags removed.
*/
public static String stripTags(String in) {
if (in == null) {
return null;
}
return stripTags(in, false);
}
/**
* This method takes a string and strips out all tags while still leaving
* <p/>
* the tag body intact.
*
* @param in
* the text to be converted.
* @param stripBRTag
* Remove BR tags.
* @return the input string with all tags removed.
*/
public static String stripTags(String in, boolean stripBRTag) {
if (in == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = in.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (!stripBRTag && i + 3 < len && input[i + 1] == 'b'
&& input[i + 2] == 'r' && input[i + 3] == '>') {
i += 3;
continue;
}
if (i > last) {
if (last > 0) {
out.append(" ");
}
out.append(input, last, i - last);
}
last = i + 1;
} else if (ch == '>') {
last = i + 1;
}
}
if (last == 0) {
return in;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* This method takes a string which may contain HTML tags (ie, <b>,
* <p/>
* <table>, etc) and converts the '<'' and '>' characters to
* <p/>
* their HTML escape sequences.
*
* @param in
* the text to be converted.
* @return the input string with the characters '<' and '>' replaced
* <p/>
* with their HTML escape sequences.
*/
public static String escapeHTMLTags(String in) {
if (in == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = in.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(LT_ENCODE);
} else if (ch == '>') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(GT_ENCODE);
} else if (ch == '"') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(QUOTE_ENCODE);
}
}
if (last == 0) {
return in;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* Used by the hash method.
*/
private static MessageDigest digest = null;
/**
* Hashes a String using the Md5 algorithm and returns the result as a
* <p/>
* String of hexadecimal numbers. This method is synchronized to avoid
* <p/>
* excessive MessageDigest object creation. If calling this method becomes
* <p/>
* a bottleneck in your code, you may wish to maintain a pool of
* <p/>
* MessageDigest objects instead of using this method.
* <p/>
* <p/>
* <p/>
* A hash is a one-way function -- that is, given an
* <p/>
* input, an output is easily computed. However, given the output, the
* <p/>
* input is almost impossible to compute. This is useful for passwords
* <p/>
* since we can store the hash and a hacker will then have a very hard time
* <p/>
* determining the original password.
* <p/>
* <p/>
* <p/>
* In Jive, every time a user logs in, we simply
* <p/>
* take their plain text password, compute the hash, and compare the
* <p/>
* generated hash to the stored hash. Since it is almost impossible that
* <p/>
* two passwords will generate the same hash, we know if the user gave us
* <p/>
* the correct password or not. The only negative to this system is that
* <p/>
* password recovery is basically impossible. Therefore, a reset password
* <p/>
* method is used instead.
*
* @param data
* the String to compute the hash of.
* @return a hashed version of the passed-in String
*/
public synchronized static String hash(String data) {
if (digest == null) {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
// Nothing to do
}
}
// Now, compute hash.
try {
digest.update(data.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
// Nothing to do
}
return encodeHex(digest.digest());
}
public synchronized static String hash(byte[] data) {
if (digest == null) {
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
// Nothing to do
}
}
// Now, compute hash.
digest.update(data);
return encodeHex(digest.digest());
}
/**
* Turns an array of bytes into a String representing each byte as an
* <p/>
* unsigned hex number.
* <p/>
* <p/>
* <p/>
* Method by Santeri Paavolainen, Helsinki Finland 1996<br>
* <p/>
* (c) Santeri Paavolainen, Helsinki Finland 1996<br>
* <p/>
* Distributed under LGPL.
*
* @param bytes
* an array of bytes to convert to a hex-string
* @return generated hex string
*/
public static String encodeHex(byte[] bytes) {
StringBuffer buf = new StringBuffer(bytes.length * 2);
int i;
for (i = 0; i < bytes.length; i++) {
if (((int) bytes[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString((int) bytes[i] & 0xff, 16));
}
return buf.toString();
}
/**
* Turns a hex encoded string into a byte array. It is specifically meant
* <p/>
* to "reverse" the toHex(byte[]) method.
*
* @param hex
* a hex encoded String to transform into a byte array.
* @return a byte array representing the hex String[
*/
public static byte[] decodeHex(String hex) {
char[] chars = hex.toCharArray();
byte[] bytes = new byte[chars.length / 2];
int byteCount = 0;
for (int i = 0; i < chars.length; i += 2) {
int newByte = 0x00;
newByte |= hexCharToByte(chars[i]);
newByte <<= 4;
newByte |= hexCharToByte(chars[i + 1]);
bytes[byteCount] = (byte) newByte;
byteCount++;
}
return bytes;
}
/**
* Returns the the byte value of a hexadecmical char (0-f). It's assumed
* <p/>
* that the hexidecimal chars are lower case as appropriate.
*
* @param ch
* a hexedicmal character (0-f)
* @return the byte value of the character (0x00-0x0F)
*/
private static byte hexCharToByte(char ch) {
switch (ch) {
case '0':
return 0x00;
case '1':
return 0x01;
case '2':
return 0x02;
case '3':
return 0x03;
case '4':
return 0x04;
case '5':
return 0x05;
case '6':
return 0x06;
case '7':
return 0x07;
case '8':
return 0x08;
case '9':
return 0x09;
case 'a':
return 0x0A;
case 'b':
return 0x0B;
case 'c':
return 0x0C;
case 'd':
return 0x0D;
case 'e':
return 0x0E;
case 'f':
return 0x0F;
}
return 0x00;
}
// *********************************************************************
// * Base64 - a simple base64 encoder and decoder.
// *
// * Copyright (c) 1999, Bob Withers - bwit@pobox.com
// *
// * This code may be freely used for any purpose, either personal
// * or commercial, provided the authors copyright notice remains
// * intact.
// *********************************************************************
/**
* Encodes a String as a base64 String.
*
* @param data
* a String to encode.
* @return a base64 encoded String.
*/
public static String encodeBase64(String data) {
byte[] bytes = null;
try {
bytes = data.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException uee) {
// Nothing to do
}
return encodeBase64(bytes);
}
/**
* Encodes a byte array into a base64 String.
*
* @param data
* a byte array to encode.
* @return a base64 encode String.
*/
public static String encodeBase64(byte[] data) {
int c;
int len = data.length;
StringBuffer ret = new StringBuffer(((len / 3) + 1) * 4);
for (int i = 0; i < len; ++i) {
c = (data[i] >> 2) & 0x3f;
ret.append(cvt.charAt(c));
c = (data[i] << 4) & 0x3f;
if (++i < len)
c |= (data[i] >> 4) & 0x0f;
ret.append(cvt.charAt(c));
if (i < len) {
c = (data[i] << 2) & 0x3f;
if (++i < len)
c |= (data[i] >> 6) & 0x03;
ret.append(cvt.charAt(c));
} else {
++i;
ret.append((char) fillchar);
}
if (i < len) {
c = data[i] & 0x3f;
ret.append(cvt.charAt(c));
} else {
ret.append((char) fillchar);
}
}
return ret.toString();
}
/**
* Decodes a base64 String.
*
* @param data
* a base64 encoded String to decode.
* @return the decoded String.
*/
public static String decodeBase64(String data) {
byte[] bytes = null;
try {
bytes = data.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException uee) {
// Nothing to do
}
return decodeBase64(bytes);
}
/**
* Decodes a base64 aray of bytes.
*
* @param data
* a base64 encode byte array to decode.
* @return the decoded String.
*/
public static String decodeBase64(byte[] data) {
int c, c1;
int len = data.length;
StringBuffer ret = new StringBuffer((len * 3) / 4);
for (int i = 0; i < len; ++i) {
c = cvt.indexOf(data[i]);
++i;
c1 = cvt.indexOf(data[i]);
c = ((c << 2) | ((c1 >> 4) & 0x3));
ret.append((char) c);
if (++i < len) {
c = data[i];
if (fillchar == c)
break;
c = cvt.indexOf(c);
c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
ret.append((char) c1);
}
if (++i < len) {
c1 = data[i];
if (fillchar == c1)
break;
c1 = cvt.indexOf(c1);
c = ((c << 6) & 0xc0) | c1;
ret.append((char) c);
}
}
return ret.toString();
}
/**
* The method below is under the following license
* <p/>
* <p/>
* <p/>
* ====================================================================
* <p/>
* <p/>
* <p/>
* The Apache Software License, Version 1.1
* <p/>
* <p/>
* <p/>
* Copyright (c) 2002-2003 The Apache Software Foundation. All rights
* <p/>
* reserved.
* <p/>
* <p/>
* <p/>
* Redistribution and use in source and binary forms, with or without
* <p/>
* modification, are permitted provided that the following conditions
* <p/>
* are met:
* <p/>
* <p/>
* <p/>
* 1. Redistributions of source code must retain the above copyright
* <p/>
* notice, this list of conditions and the following disclaimer.
* <p/>
* <p/>
* <p/>
* 2. Redistributions in binary form must reproduce the above copyright
* <p/>
* notice, this list of conditions and the following disclaimer in
* <p/>
* the documentation and/or other materials provided with the
* <p/>
* distribution.
* <p/>
* <p/>
* <p/>
* 3. The end-user documentation included with the redistribution, if
* <p/>
* any, must include the following acknowlegement:
* <p/>
* "This product includes software developed by the
* <p/>
* Apache Software Foundation (http://www.apache.org/)."
* <p/>
* Alternately, this acknowlegement may appear in the software itself,
* <p/>
* if and wherever such third-party acknowlegements normally appear.
* <p/>
* <p/>
* <p/>
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* <p/>
* Foundation" must not be used to endorse or promote products derived
* <p/>
* from this software without prior written permission. For written
* <p/>
* permission, please contact apache@apache.org.
* <p/>
* <p/>
* <p/>
* 5. Products derived from this software may not be called "Apache"
* <p/>
* nor may "Apache" appear in their names without prior written
* <p/>
* permission of the Apache Group.
* <p/>
* <p/>
* <p/>
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* <p/>
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* <p/>
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* <p/>
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* <p/>
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* <p/>
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* <p/>
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* <p/>
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* <p/>
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* <p/>
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* <p/>
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* <p/>
* SUCH DAMAGE.
* <p/>
* ====================================================================
* <p/>
* <p/>
* <p/>
* This software consists of voluntary contributions made by many
* <p/>
* individuals on behalf of the Apache Software Foundation. For more
* <p/>
* information on the Apache Software Foundation, please see
* <p/>
* <http://www.apache.org/>.
*/
private static final BitSet allowed_query = new BitSet(256);
static {
for (int i = '0'; i <= '9'; i++) {
allowed_query.set(i);
}
for (int i = 'a'; i <= 'z'; i++) {
allowed_query.set(i);
}
for (int i = 'A'; i <= 'Z'; i++) {
allowed_query.set(i);
}
allowed_query.set('-');
allowed_query.set('_');
allowed_query.set('.');
allowed_query.set('!');
allowed_query.set('~');
allowed_query.set('*');
allowed_query.set('\'');
allowed_query.set('(');
allowed_query.set(')');
}
/**
* Encodes URI string. This is a replacement for the
* java.net.URLEncode#encode(String, String)
* <p/>
* class which is broken under JDK 1.3.
* <p/>
* <p/>
*
* @param original
* the original character sequence
* @param charset
* the protocol charset
* @return URI character sequence
* @throws UnsupportedEncodingException
* unsupported character encoding
*/
public static String URLEncode(String original, String charset)
throws UnsupportedEncodingException {
// encode original to uri characters.
if (original == null) {
return null;
}
// escape octet to uri characters.
byte[] octets;
try {
octets = original.getBytes(charset);
} catch (UnsupportedEncodingException error) {
throw new UnsupportedEncodingException();
}
StringBuffer buf = new StringBuffer(octets.length);
for (byte octet : octets) {
char c = (char) octet;
if (allowed_query.get(c)) {
buf.append(c);
} else {
buf.append('%');
char hexadecimal = Character.forDigit((octet >> 4) & 0xF, 16);
buf.append(Character.toUpperCase(hexadecimal)); // high
hexadecimal = Character.forDigit(octet & 0xF, 16);
buf.append(Character.toUpperCase(hexadecimal)); // low
}
}
return buf.toString();
}
private static final int fillchar = '=';
private static final String cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz" + "0123456789+/";
/**
* Converts a line of text into an array of lower case words using a
* <p/>
* BreakIterator.wordInstance().
* <p>
* <p/>
* <p/>
* <p/>
* This method is under the Jive Open Source Software License and was
* <p/>
* written by Mark Imbriaco.
*
* @param text
* a String of text to convert into an array of words
* @return text broken up into an array of words.
*/
public static String[] toLowerCaseWordArray(String text) {
if (text == null || text.length() == 0) {
return new String[0];
}
ArrayList<String> wordList = new ArrayList<String>();
BreakIterator boundary = BreakIterator.getWordInstance();
boundary.setText(text);
int start = 0;
for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary
.next()) {
String tmp = text.substring(start, end).trim();
// Remove characters that are not needed.
tmp = replace(tmp, "+", "");
tmp = replace(tmp, "/", "");
tmp = replace(tmp, "\\", "");
tmp = replace(tmp, "#", "");
tmp = replace(tmp, "*", "");
tmp = replace(tmp, ")", "");
tmp = replace(tmp, "(", "");
tmp = replace(tmp, "&", "");
if (tmp.length() > 0) {
wordList.add(tmp);
}
}
return wordList.toArray(new String[wordList.size()]);
}
/**
* Pseudo-random number generator object for use with randomString().
* <p/>
* The Random class is not considered to be cryptographically secure, so
* <p/>
* only use these random Strings for low to medium security applications.
*/
private static Random randGen = new Random();
/**
* Array of numbers and letters of mixed case. Numbers appear in the list
* <p/>
* twice so that there is a more equal chance that a number will be picked.
* <p/>
* We can use the array to get a random number or letter by picking a random
* <p/>
* array index.
*/
private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
/**
* Returns a random String of numbers and letters (lower and upper case)
* <p/>
* of the specified length. The method uses the Random class that is
* <p/>
* built-in to Java which is suitable for low to medium grade security uses.
* <p/>
* This means that the output is only pseudo random, i.e., each number is
* <p/>
* mathematically generated so is not truly random.
* <p>
* <p/>
* <p/>
* <p/>
* The specified length must be at least one. If not, the method will return
* <p/>
* null.
*
* @param length
* the desired length of the random String to return.
* @return a random String of numbers and letters of the specified length.
*/
public static String randomString(int length) {
if (length < 1) {
return null;
}
// Create a char buffer to put random letters and numbers in.
char[] randBuffer = new char[length];
for (int i = 0; i < randBuffer.length; i++) {
randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
}
return new String(randBuffer);
}
/**
* Intelligently chops a String at a word boundary (whitespace) that occurs
* <p/>
* at the specified index in the argument or before. However, if there is a
* <p/>
* newline character before <code>length</code>, the String will be chopped
* <p/>
* there. If no newline or whitespace is found in <code>string</code> up to
* <p/>
* the index <code>length</code>, the String will chopped at
* <code>length</code>.
* <p/>
* <p/>
* <p/>
* For example, chopAtWord("This is a nice String", 10, -1) will return
* <p/>
* "This is a" which is the first word boundary less than or equal to 10
* <p/>
* characters into the original String.
*
* @param string
* the String to chop.
* @param length
* the index in <code>string</code> to start looking for a
* <p/>
* whitespace boundary at.
* @param minLength
* the minimum length the word should be chopped at. This is
* helpful
* <p/>
* for words with no natural boundaries, ie:
* "thisisareallylonglonglongword".
* <p/>
* This must be smaller than length and can be -1 if no minLength
* is wanted
* @return a substring of <code>string</code> whose length is less than or
* <p/>
* equal to <code>length</code>, and that is chopped at whitespace.
*/
public static String chopAtWord(String string, int length, int minLength) {
// guard clauses
if (length < 2) {
throw new IllegalArgumentException("Length specified (" + length
+ ") must be > 2");
} else if (minLength >= length) {
throw new IllegalArgumentException(
"minLength must be smaller than length");
}
int sLength = (string == null) ? -1 : string.length();
// shortcircuit clauses
if (sLength < 1) {
return string;
}
// minLength specified, string is smaller than the minLength, return the
// string
else if (minLength != -1 && sLength < minLength) {
return string;
}
// no minLength specified, string is smaller than length
else if (minLength == -1 && sLength < length) {
return string;
}
if (string == null)
return null;
char[] charArray = string.toCharArray();
// String is longer than the length specified, attempt to find a newline
// or a space
if (sLength > length) {
sLength = length;
// First check if there is a newline character before length; if so,
// chop word there.
for (int i = 0; i < sLength - 1; i++) {
// Windows
if (charArray[i] == '\r' && charArray[i + 1] == '\n') {
return string.substring(0, i + 1);
}
// Unix
else if (charArray[i] == '\n') {
return string.substring(0, i);
}
}
// Also check boundary case of Unix newline
if (charArray[sLength - 1] == '\n') {
return string.substring(0, sLength - 1);
}
// No newline, so chop at the first whitespace.
for (int i = sLength - 1; i > 0; i--) {
if (charArray[i] == ' ') {
return string.substring(0, i).trim();
}
}
}
// String is shorter than length but longer than minLength,
// make sure there is a space in the string before minLength
else if (minLength != -1 && sLength > minLength) {
for (int i = 0; i < minLength; i++) {
if (charArray[i] == ' ') {
return string;
}
}
}
// Did not find a word boundary, so return a string at the min length,
// if a min
// length was specified:
if (minLength > -1 && minLength <= string.length()) {
return string.substring(0, minLength);
}
// Did not find word boundary or min length so return original String
// chopped at
// specified length.
return string.substring(0, length);
}
/**
* Intelligently chops a String at a word boundary (whitespace) that occurs
* <p/>
* at the specified index in the argument or before. However, if there is a
* <p/>
* newline character before <code>length</code>, the String will be chopped
* <p/>
* there. If no newline or whitespace is found in <code>string</code> up to
* <p/>
* the index <code>length</code>, the String will chopped at
* <code>length</code>.
* <p/>
* <p/>
* <p/>
* For example, chopAtWord("This is a nice String", 10) will return
* <p/>
* "This is a" which is the first word boundary less than or equal to 10
* <p/>
* characters into the original String.
*
* @param string
* the String to chop.
* @param length
* the index in <code>string</code> to start looking for a
* <p/>
* whitespace boundary at.
* @return a substring of <code>string</code> whose length is less than or
* <p/>
* equal to <code>length</code>, and that is chopped at whitespace.
*/
public static String chopAtWord(String string, int length) {
return chopAtWord(string, length, -1);
}
/**
* Returns a substring of the given string which represents the words around
* the given word.
* <p/>
* For example, passing in "This is a quick test a test", "{a,test}" and 5
* would return a string
* <p/>
* of "This is a quick" - that's 5 characters (or to the end of the word,
* whichever
* <p/>
* is greater) on either side of "a". Also, since {a,test} is passed in a
* "a" is found
* <p/>
* first in the string, we base the substring off of the position of "a".
* The wordList is
* <p/>
* really just a list of strings to try - the first one found is used.
* <p>
* <p/>
* <p/>
* <p/>
* Note: The wordList passed in should be lowercase.
*
* @param input
* The string to parse.
* @param wordList
* The words to look for - the first one found in the string is
* used.
* @param numChars
* The number of characters on either side to include in the
* chop.
* @return a substring of the given string matching the criteria, otherwise
* "".
*/
public static String chopAtWordsAround(String input, String[] wordList,
int numChars) {
if (input == null || "".equals(input.trim()) || wordList == null
|| wordList.length == 0 || numChars == 0) {
return "";
}
String lc = input.toLowerCase();
for (String aWordList : wordList) {
int pos = lc.indexOf(aWordList);
if (pos > -1) {
int beginIdx = pos - numChars;
if (beginIdx < 0) {
beginIdx = 0;
}
int endIdx = pos + numChars;
if (endIdx > input.length() - 1) {
endIdx = input.length() - 1;
}
char[] chars = input.toCharArray();
while (beginIdx > 0 && chars[beginIdx] != ' '
&& chars[beginIdx] != '\n' && chars[beginIdx] != '\r') {
beginIdx--;
}
while (endIdx < input.length() && chars[endIdx] != ' '
&& chars[endIdx] != '\n' && chars[endIdx] != '\r') {
endIdx++;
}
return input.substring(beginIdx, endIdx);
}
}
return input.substring(0,
(input.length() >= 200) ? 200 : input.length());
}
/**
* Reformats a string where lines that are longer than <tt>width</tt>
* <p/>
* are split apart at the earliest wordbreak or at maxLength, whichever is
* <p/>
* sooner. If the width specified is less than 5 or greater than the input
* <p/>
* Strings length the string will be returned as is.
* <p/>
* <p/>
* <p/>
* Please note that this method can be lossy - trailing spaces on wrapped
* <p/>
* lines may be trimmed.
*
* @param input
* the String to reformat.
* @param width
* the maximum length of any one line.
* @param locale
* of the string to be wrapped.
* @return a new String with reformatted as needed.
*/
public static String wordWrap(String input, int width, Locale locale) {
// protect ourselves
if (input == null) {
return "";
} else if (width < 5) {
return input;
} else if (width >= input.length()) {
return input;
}
StringBuffer buf = new StringBuffer(input);
boolean endOfLine = false;
int lineStart = 0;
for (int i = 0; i < buf.length(); i++) {
if (buf.charAt(i) == '\n') {
lineStart = i + 1;
endOfLine = true;
}
// handle splitting at width character
if (i > lineStart + width - 1) {
if (!endOfLine) {
int limit = i - lineStart - 1;
BreakIterator breaks = BreakIterator
.getLineInstance(locale);
breaks.setText(buf.substring(lineStart, i));
int end = breaks.last();
// if the last character in the search string isn't a space,
// we can't split on it (looks bad). Search for a previous
// break character
if (end == limit + 1) {
if (!Character
.isWhitespace(buf.charAt(lineStart + end))) {
end = breaks.preceding(end - 1);
}
}
// if the last character is a space, replace it with a \n
if (end != BreakIterator.DONE && end == limit + 1) {
buf.replace(lineStart + end, lineStart + end + 1, "\n");
lineStart = lineStart + end;
}
// otherwise, just insert a \n
else if (end != BreakIterator.DONE && end != 0) {
buf.insert(lineStart + end, '\n');
lineStart = lineStart + end + 1;
} else {
buf.insert(i, '\n');
lineStart = i + 1;
}
} else {
buf.insert(i, '\n');
lineStart = i + 1;
endOfLine = false;
}
}
}
return buf.toString();
}
/**
* Highlights words in a string. Words matching ignores case. The actual
* <p/>
* higlighting method is specified with the start and end higlight tags.
* <p/>
* Those might be beginning and ending HTML bold tags, or anything else.
* <p>
* <p/>
* <p/>
* <p/>
* This method is under the Jive Open Source Software License and was
* <p/>
* written by Mark Imbriaco.
*
* @param string
* the String to highlight words in.
* @param words
* an array of words that should be highlighted in the string.
* @param startHighlight
* the tag that should be inserted to start highlighting.
* @param endHighlight
* the tag that should be inserted to end highlighting.
* @return a new String with the specified words highlighted.
*/
public static String highlightWords(String string, String[] words,
String startHighlight, String endHighlight) {
if (string == null || words == null || startHighlight == null
|| endHighlight == null) {
return null;
}
StringBuffer regexp = new StringBuffer();
regexp.append("(?i)\\b(");
// Iterate through each word and generate a word list for the regexp.
for (int x = 0; x < words.length; x++) {
// Escape "$", "|", ".", "/", and "?" to keep us out of trouble in
// our regexp.
words[x] = words[x].replaceAll("([\\$\\?\\|\\/\\.])", "\\\\$1");
regexp.append(words[x]);
if (x != words.length - 1) {
regexp.append("|");
}
}
regexp.append(")");
return string.replaceAll(regexp.toString(), startHighlight + "$1"
+ endHighlight);
}
/**
* Escapes all necessary characters in the String so that it can be used
* <p/>
* in an XML doc.
*
* @param string
* the string to escape.
* @return the string with appropriate characters escaped.
*/
public static String escapeForXML(String string) {
if (string == null) {
return null;
}
char ch;
int i = 0;
int last = 0;
char[] input = string.toCharArray();
int len = input.length;
StringBuffer out = new StringBuffer((int) (len * 1.3));
for (; i < len; i++) {
ch = input[i];
if (ch > '>') {
// Nothing to do
} else if (ch == '<') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(LT_ENCODE);
} else if (ch == '&') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(AMP_ENCODE);
} else if (ch == '"') {
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
out.append(QUOTE_ENCODE);
} else if (ch == 10 || ch == 13 || ch == 9) {
// Nothing to do
} else if (ch < 32) {
// Disallow all ASCII control characters, except space,
// enter characters and tabs:
if (i > last) {
out.append(input, last, i - last);
}
last = i + 1;
}
}
if (last == 0) {
return string;
}
if (i > last) {
out.append(input, last, i - last);
}
return out.toString();
}
/**
* Unescapes the String by converting XML escape sequences back into normal
* <p/>
* characters.
*
* @param string
* the string to unescape.
* @return the string with appropriate characters unescaped.
*/
public static String unescapeFromXML(String string) {
string = replace(string, "<", "<");
string = replace(string, ">", ">");
string = replace(string, """, "\"");
return replace(string, "&", "&");
}
private static final char[] zeroArray = "0000000000000000000000000000000000000000000000000000000000000000"
.toCharArray();
/**
* Pads the supplied String with 0's to the specified length and returns
* <p/>
* the result as a new String. For example, if the initial String is
* <p/>
* "9999" and the desired length is 8, the result would be "00009999".
* <p/>
* This type of padding is useful for creating numerical values that need
* <p/>
* to be stored and sorted as character data. Note: the current
* <p/>
* implementation of this method allows for a maximum <tt>length</tt> of
* <p/>
* 64.
*
* @param string
* the original String to pad.
* @param length
* the desired length of the new padded String.
* @return a new String padded with the required number of 0's.
*/
public static String zeroPadString(String string, int length) {
if (string == null || string.length() > length) {
return string;
}
StringBuffer buf = new StringBuffer(length);
buf.append(zeroArray, 0, length - string.length()).append(string);
return buf.toString();
}
/**
* Formats a Date as a String. Depending on how Dates are defined in the
* database
* <p/>
* (character data or numberic), the format return will either be a fifteen
* character long String
* <p/>
* made up of the Date's padded millisecond value, or will simply be the
* Date's millesecond value.
*
* @param date
* Date to convert to milliseconds.
* @return a Date encoded as a String.
*/
public static String dateToMillis(Date date) {
return Long.toString(date.getTime());
}
/**
* Validate an email address. This isn't 100% perfect but should handle just
* about everything
* <p/>
* that is in common use.
*
* @param addr
* the email address to validate
* @return true if the address is valid, false otherwise
*/
public static boolean isValidEmailAddress(String addr) {
if (addr == null) {
return false;
}
addr = addr.trim();
if (addr.length() == 0) {
return false;
}
// basic address check
Matcher matcher = basicAddressPattern.matcher(addr);
if (!matcher.matches()) {
return false;
}
String userPart = matcher.group(1);
String domainPart = matcher.group(2);
// user address check
matcher = validUserPattern.matcher(userPart);
if (!matcher.matches()) {
return false;
}
// ip domain check
matcher = ipDomainPattern.matcher(domainPart);
if (matcher.matches()) {
// if the pattern matched, check to make sure that the ip range is
// valid
for (int i = 1; i < 5; i++) {
String num = matcher.group(i);
if (num == null) {
return false;
}
if (Integer.parseInt(num) > 254) {
return false;
}
}
return true;
}
// symbolic domain check
matcher = domainPattern.matcher(domainPart);
if (matcher.matches()) {
String tld = matcher.group(matcher.groupCount());
// Permit top-level-domains of 3 (includes dot separator) because
// these could be
// country codes which we are not going to check for.
matcher = tldPattern.matcher(tld);
if (tld.length() != 3 && !matcher.matches()) {
return false;
}
} else {
return false;
}
// all tests passed
return true;
}
// Testing method
/*
* public static void main(String[] args) { { String test1 =
* "The quick brown fox jumped"; int chop11 = test1.length(); int chop12 =
* test1.length() - 1; int chop13 = test1.length() - 3; int chop14 =
* test1.length() - "jumped".length(); int chop15 = test1.length() -
* "ox jumped".length(); // run test 1 String result11 = chopAtWord(test1,
* chop11); String result12 = chopAtWord(test1, chop12); String result13 =
* chopAtWord(test1, chop13); String result14 = chopAtWord(test1, chop14);
* String result15 = chopAtWord(test1, chop15); // print results if
* (test1.equals(result11)) { System.err.println("Test 1.1 passed, result: "
* + result11); } else { System.err.println("Test 1.1 failed, result: " +
* result11); }
*
* if ("The quick brown fox".equals(result12)) {
* System.err.println("Test 1.2 passed, result: " + result12); } else {
* System.err.println("Test 1.2 failed, result: " + result12); }
*
* if ("The quick brown fox".equals(result13)) {
* System.err.println("Test 1.3 passed, result: " + result13); } else {
* System.err.println("Test 1.3 failed, result: " + result13); }
*
* if ("The quick brown fox".equals(result14)) {
* System.err.println("Test 1.4 passed, result: " + result14); } else {
* System.err.println("Test 1.4 failed, result: " + result14); }
*
* if ("The quick brown".equals(result15)) {
* System.err.println("Test 1.5 passed, result: " + result15); } else {
* System.err.println("Test 1.5 failed, result: " + result15); } }
*
* System.err.println("");
*
* { String test2 = "The quick brown fox jumped"; int chop21 =
* test2.length(); int chop22 = test2.length() - 1; int chop23 =
* test2.length() - 3; int chop24 = test2.length() - "jumped".length(); int
* chop25 = test2.length() - "ox jumped".length(); // run test 1 String
* result21 = chopAtWord(test2, chop21, 0); String result22 =
* chopAtWord(test2, chop22, 0); String result23 = chopAtWord(test2, chop23,
* 0); String result24 = chopAtWord(test2, chop24, 0); String result25 =
* chopAtWord(test2, chop25, 0); // print results if
* (test2.equals(result21)) { System.err.println("Test 2.1 passed, result: "
* + result21); } else { System.err.println("Test 2.1 failed, result: " +
* result21); }
*
* if ("The quick brown fox".equals(result22)) {
* System.err.println("Test 2.2 passed, result: " + result22); } else {
* System.err.println("Test 2.2 failed, result: " + result22); }
*
* if ("The quick brown fox".equals(result23)) {
* System.err.println("Test 2.3 passed, result: " + result23); } else {
* System.err.println("Test 2.3 failed, result: " + result23); }
*
* if ("The quick brown fox".equals(result24)) {
* System.err.println("Test 2.4 passed, result: " + result24); } else {
* System.err.println("Test 2.4 failed, result: " + result24); }
*
* if ("The quick brown".equals(result25)) {
* System.err.println("Test 2.5 passed, result: " + result25); } else {
* System.err.println("Test 2.5 failed, result: " + result25); } }
*
* System.err.println("");
*
* { String test3 = "Thequickbrownfoxjumped"; int chop31 = test3.length();
* int chop32 = test3.length() - 1; int chop33 = test3.length() - 3; int
* chop34 = test3.length() - "jumped".length(); int chop35 = test3.length()
* - "ox jumped".length(); // run test 1 String result31 = chopAtWord(test3,
* chop31, "Thequickbrownfoxjumped".length()); String result32 =
* chopAtWord(test3, chop32, "Thequick".length()); String result33 =
* chopAtWord(test3, chop33, "Thequick".length()); String result34 =
* chopAtWord(test3, chop34, "Thequick".length()); String result35 =
* chopAtWord(test3, chop35, "Thequick".length()); // print results if
* ("Thequick".equals(result31)) {
* System.err.println("Test 3.1 passed, result: " + result31); } else {
* System.err.println("Test 3.1 failed, result: " + result31); }
*
* if ("Thequick".equals(result32)) {
* System.err.println("Test 3.2 passed, result: " + result32); } else {
* System.err.println("Test 3.2 failed, result: " + result32); }
*
* if ("Thequick".equals(result33)) {
* System.err.println("Test 3.3 passed, result: " + result33); } else {
* System.err.println("Test 3.3 failed, result: " + result33); }
*
* if ("Thequick".equals(result34)) {
* System.err.println("Test 3.4 passed, result: " + result34); } else {
* System.err.println("Test 3.4 failed, result: " + result34); }
*
* if ("Thequick".equals(result35)) {
* System.err.println("Test 3.5 passed, result: " + result35); } else {
* System.err.println("Test 3.5 failed, result: " + result35); } }
*
* System.err.println("");
*
* { String test4 = "Java.Lang.ClassNotFoundException:com.Citrix"; int
* length = test4.length()-3; int min = 20; String result =
* chopAtWord(test4, length, min); System.err.println("result: " + result);
* } }
*/
public static String keyStroke2String(KeyStroke key) {
StringBuffer s = new StringBuffer(50);
int m = key.getModifiers();
if ((m & (InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)) != 0) {
s.append("shift ");
}
if ((m & (InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)) != 0) {
s.append("ctrl ");
}
if ((m & (InputEvent.META_DOWN_MASK | InputEvent.META_MASK)) != 0) {
s.append("meta ");
}
if ((m & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)) != 0) {
s.append("alt ");
}
if ((m & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON1_MASK)) != 0) {
s.append("button1 ");
}
if ((m & (InputEvent.BUTTON2_DOWN_MASK | InputEvent.BUTTON2_MASK)) != 0) {
s.append("button2 ");
}
if ((m & (InputEvent.BUTTON3_DOWN_MASK | InputEvent.BUTTON3_MASK)) != 0) {
s.append("button3 ");
}
switch (key.getKeyEventType()) {
case KeyEvent.KEY_TYPED:
s.append("typed ");
s.append(key.getKeyChar()).append(" ");
break;
case KeyEvent.KEY_PRESSED:
s.append("pressed ");
s.append(getKeyText(key.getKeyCode())).append(" ");
break;
case KeyEvent.KEY_RELEASED:
s.append("released ");
s.append(getKeyText(key.getKeyCode())).append(" ");
break;
default:
s.append("unknown-event-type ");
break;
}
return s.toString();
}
public static String getKeyText(int keyCode) {
if (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9
|| keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) {
return String.valueOf((char) keyCode);
}
switch (keyCode) {
case KeyEvent.VK_COMMA:
return "COMMA";
case KeyEvent.VK_PERIOD:
return "PERIOD";
case KeyEvent.VK_SLASH:
return "SLASH";
case KeyEvent.VK_SEMICOLON:
return "SEMICOLON";
case KeyEvent.VK_EQUALS:
return "EQUALS";
case KeyEvent.VK_OPEN_BRACKET:
return "OPEN_BRACKET";
case KeyEvent.VK_BACK_SLASH:
return "BACK_SLASH";
case KeyEvent.VK_CLOSE_BRACKET:
return "CLOSE_BRACKET";
case KeyEvent.VK_ENTER:
return "ENTER";
case KeyEvent.VK_BACK_SPACE:
return "BACK_SPACE";
case KeyEvent.VK_TAB:
return "TAB";
case KeyEvent.VK_CANCEL:
return "CANCEL";
case KeyEvent.VK_CLEAR:
return "CLEAR";
case KeyEvent.VK_SHIFT:
return "SHIFT";
case KeyEvent.VK_CONTROL:
return "CONTROL";
case KeyEvent.VK_ALT:
return "ALT";
case KeyEvent.VK_PAUSE:
return "PAUSE";
case KeyEvent.VK_CAPS_LOCK:
return "CAPS_LOCK";
case KeyEvent.VK_ESCAPE:
return "ESCAPE";
case KeyEvent.VK_SPACE:
return "SPACE";
case KeyEvent.VK_PAGE_UP:
return "PAGE_UP";
case KeyEvent.VK_PAGE_DOWN:
return "PAGE_DOWN";
case KeyEvent.VK_END:
return "END";
case KeyEvent.VK_HOME:
return "HOME";
case KeyEvent.VK_LEFT:
return "LEFT";
case KeyEvent.VK_UP:
return "UP";
case KeyEvent.VK_RIGHT:
return "RIGHT";
case KeyEvent.VK_DOWN:
return "DOWN";
// numpad numeric keys handled below
case KeyEvent.VK_MULTIPLY:
return "MULTIPLY";
case KeyEvent.VK_ADD:
return "ADD";
case KeyEvent.VK_SEPARATOR:
return "SEPARATOR";
case KeyEvent.VK_SUBTRACT:
return "SUBTRACT";
case KeyEvent.VK_DECIMAL:
return "DECIMAL";
case KeyEvent.VK_DIVIDE:
return "DIVIDE";
case KeyEvent.VK_DELETE:
return "DELETE";
case KeyEvent.VK_NUM_LOCK:
return "NUM_LOCK";
case KeyEvent.VK_SCROLL_LOCK:
return "SCROLL_LOCK";
case KeyEvent.VK_F1:
return "F1";
case KeyEvent.VK_F2:
return "F2";
case KeyEvent.VK_F3:
return "F3";
case KeyEvent.VK_F4:
return "F4";
case KeyEvent.VK_F5:
return "F5";
case KeyEvent.VK_F6:
return "F6";
case KeyEvent.VK_F7:
return "F7";
case KeyEvent.VK_F8:
return "F8";
case KeyEvent.VK_F9:
return "F9";
case KeyEvent.VK_F10:
return "F10";
case KeyEvent.VK_F11:
return "F11";
case KeyEvent.VK_F12:
return "F12";
case KeyEvent.VK_F13:
return "F13";
case KeyEvent.VK_F14:
return "F14";
case KeyEvent.VK_F15:
return "F15";
case KeyEvent.VK_F16:
return "F16";
case KeyEvent.VK_F17:
return "F17";
case KeyEvent.VK_F18:
return "F18";
case KeyEvent.VK_F19:
return "F19";
case KeyEvent.VK_F20:
return "F20";
case KeyEvent.VK_F21:
return "F21";
case KeyEvent.VK_F22:
return "F22";
case KeyEvent.VK_F23:
return "F23";
case KeyEvent.VK_F24:
return "F24";
case KeyEvent.VK_PRINTSCREEN:
return "PRINTSCREEN";
case KeyEvent.VK_INSERT:
return "INSERT";
case KeyEvent.VK_HELP:
return "HELP";
case KeyEvent.VK_META:
return "META";
case KeyEvent.VK_BACK_QUOTE:
return "BACK_QUOTE";
case KeyEvent.VK_QUOTE:
return "QUOTE";
case KeyEvent.VK_KP_UP:
return "KP_UP";
case KeyEvent.VK_KP_DOWN:
return "KP_DOWN";
case KeyEvent.VK_KP_LEFT:
return "KP_LEFT";
case KeyEvent.VK_KP_RIGHT:
return "KP_RIGHT";
case KeyEvent.VK_DEAD_GRAVE:
return "DEAD_GRAVE";
case KeyEvent.VK_DEAD_ACUTE:
return "DEAD_ACUTE";
case KeyEvent.VK_DEAD_CIRCUMFLEX:
return "DEAD_CIRCUMFLEX";
case KeyEvent.VK_DEAD_TILDE:
return "DEAD_TILDE";
case KeyEvent.VK_DEAD_MACRON:
return "DEAD_MACRON";
case KeyEvent.VK_DEAD_BREVE:
return "DEAD_BREVE";
case KeyEvent.VK_DEAD_ABOVEDOT:
return "DEAD_ABOVEDOT";
case KeyEvent.VK_DEAD_DIAERESIS:
return "DEAD_DIAERESIS";
case KeyEvent.VK_DEAD_ABOVERING:
return "DEAD_ABOVERING";
case KeyEvent.VK_DEAD_DOUBLEACUTE:
return "DEAD_DOUBLEACUTE";
case KeyEvent.VK_DEAD_CARON:
return "DEAD_CARON";
case KeyEvent.VK_DEAD_CEDILLA:
return "DEAD_CEDILLA";
case KeyEvent.VK_DEAD_OGONEK:
return "DEAD_OGONEK";
case KeyEvent.VK_DEAD_IOTA:
return "DEAD_IOTA";
case KeyEvent.VK_DEAD_VOICED_SOUND:
return "DEAD_VOICED_SOUND";
case KeyEvent.VK_DEAD_SEMIVOICED_SOUND:
return "DEAD_SEMIVOICED_SOUND";
case KeyEvent.VK_AMPERSAND:
return "AMPERSAND";
case KeyEvent.VK_ASTERISK:
return "ASTERISK";
case KeyEvent.VK_QUOTEDBL:
return "QUOTEDBL";
case KeyEvent.VK_LESS:
return "LESS";
case KeyEvent.VK_GREATER:
return "GREATER";
case KeyEvent.VK_BRACELEFT:
return "BRACELEFT";
case KeyEvent.VK_BRACERIGHT:
return "BRACERIGHT";
case KeyEvent.VK_AT:
return "AT";
case KeyEvent.VK_COLON:
return "COLON";
case KeyEvent.VK_CIRCUMFLEX:
return "CIRCUMFLEX";
case KeyEvent.VK_DOLLAR:
return "DOLLAR";
case KeyEvent.VK_EURO_SIGN:
return "EURO_SIGN";
case KeyEvent.VK_EXCLAMATION_MARK:
return "EXCLAMATION_MARK";
case KeyEvent.VK_INVERTED_EXCLAMATION_MARK:
return "INVERTED_EXCLAMATION_MARK";
case KeyEvent.VK_LEFT_PARENTHESIS:
return "LEFT_PARENTHESIS";
case KeyEvent.VK_NUMBER_SIGN:
return "NUMBER_SIGN";
case KeyEvent.VK_MINUS:
return "MINUS";
case KeyEvent.VK_PLUS:
return "PLUS";
case KeyEvent.VK_RIGHT_PARENTHESIS:
return "RIGHT_PARENTHESIS";
case KeyEvent.VK_UNDERSCORE:
return "UNDERSCORE";
case KeyEvent.VK_FINAL:
return "FINAL";
case KeyEvent.VK_CONVERT:
return "CONVERT";
case KeyEvent.VK_NONCONVERT:
return "NONCONVERT";
case KeyEvent.VK_ACCEPT:
return "ACCEPT";
case KeyEvent.VK_MODECHANGE:
return "MODECHANGE";
case KeyEvent.VK_KANA:
return "KANA";
case KeyEvent.VK_KANJI:
return "KANJI";
case KeyEvent.VK_ALPHANUMERIC:
return "ALPHANUMERIC";
case KeyEvent.VK_KATAKANA:
return "KATAKANA";
case KeyEvent.VK_HIRAGANA:
return "HIRAGANA";
case KeyEvent.VK_FULL_WIDTH:
return "FULL_WIDTH";
case KeyEvent.VK_HALF_WIDTH:
return "HALF_WIDTH";
case KeyEvent.VK_ROMAN_CHARACTERS:
return "ROMAN_CHARACTERS";
case KeyEvent.VK_ALL_CANDIDATES:
return "ALL_CANDIDATES";
case KeyEvent.VK_PREVIOUS_CANDIDATE:
return "PREVIOUS_CANDIDATE";
case KeyEvent.VK_CODE_INPUT:
return "CODE_INPUT";
case KeyEvent.VK_JAPANESE_KATAKANA:
return "JAPANESE_KATAKANA";
case KeyEvent.VK_JAPANESE_HIRAGANA:
return "JAPANESE_HIRAGANA";
case KeyEvent.VK_JAPANESE_ROMAN:
return "JAPANESE_ROMAN";
case KeyEvent.VK_KANA_LOCK:
return "KANA_LOCK";
case KeyEvent.VK_INPUT_METHOD_ON_OFF:
return "INPUT_METHOD_ON_OFF";
case KeyEvent.VK_AGAIN:
return "AGAIN";
case KeyEvent.VK_UNDO:
return "UNDO";
case KeyEvent.VK_COPY:
return "COPY";
case KeyEvent.VK_PASTE:
return "PASTE";
case KeyEvent.VK_CUT:
return "CUT";
case KeyEvent.VK_FIND:
return "FIND";
case KeyEvent.VK_PROPS:
return "PROPS";
case KeyEvent.VK_STOP:
return "STOP";
case KeyEvent.VK_COMPOSE:
return "COMPOSE";
case KeyEvent.VK_ALT_GRAPH:
return "ALT_GRAPH";
}
if (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9) {
char c = (char) (keyCode - KeyEvent.VK_NUMPAD0 + '0');
return "NUMPAD" + c;
}
return "unknown(0x" + Integer.toString(keyCode, 16) + ")";
}
public static String makeFirstWordCaptial(String word) {
if (word.length() < 2) {
return word;
}
String firstWord = word.substring(0, 1);
String restOfWord = word.substring(1);
return firstWord.toUpperCase() + restOfWord;
}
}
package PreD.utils;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
/**
*
* @Description <code>GraphicsUtils</code> class defines common user-interface
* related utility functions.
* @Author zhangzuoqiang
* @Date 2012-1-12
*/
public final class GraphicUtils {
private static final Insets HIGHLIGHT_INSETS = new Insets(1, 1, 1, 1);
public static final Color SELECTION_COLOR = new Color(166, 202, 240);
public static final Color TOOLTIP_COLOR = new Color(166, 202, 240);
protected final static Component component = new Component() {
/**
*
*/
private static final long serialVersionUID = 1L;
};
protected final static MediaTracker tracker = new MediaTracker(component);
private static Map<String, Image> imageCache = new HashMap<String, Image>();
/**
* The default Hand cursor.
*/
public static final Cursor HAND_CURSOR = new Cursor(Cursor.HAND_CURSOR);
/**
* The default Text Cursor.
*/
public static final Cursor DEFAULT_CURSOR = new Cursor(
Cursor.DEFAULT_CURSOR);
/**
* Sets the location of the specified window so that it is centered on
* screen.
*
* @param window
* The window to be centered.
*/
public static void centerWindowOnScreen(Window window) {
final Dimension screenSize = Toolkit.getDefaultToolkit()
.getScreenSize();
final Dimension size = window.getSize();
if (size.height > screenSize.height) {
size.height = screenSize.height;
}
if (size.width > screenSize.width) {
size.width = screenSize.width;
}
window.setLocation((screenSize.width - size.width) / 2,
(screenSize.height - size.height) / 2);
}
/**
* Draws a single-line highlight border rectangle.
*
* @param g
* The graphics context to use for drawing.
* @param x
* The left edge of the border.
* @param y
* The top edge of the border.
* @param width
* The width of the border.
* @param height
* The height of the border.
* @param raised
* <code>true</code> if the border is to be drawn raised,
* <code>false</code> if lowered.
* @param shadow
* The shadow color for the border.
* @param highlight
* The highlight color for the border.
* @see javax.swing.border.EtchedBorder
*/
public static void drawHighlightBorder(Graphics g, int x, int y, int width,
int height, boolean raised, Color shadow, Color highlight) {
final Color oldColor = g.getColor();
g.translate(x, y);
g.setColor(raised ? highlight : shadow);
g.drawLine(0, 0, width - 2, 0);
g.drawLine(0, 1, 0, height - 2);
g.setColor(raised ? shadow : highlight);
g.drawLine(width - 1, 0, width - 1, height - 1);
g.drawLine(0, height - 1, width - 2, height - 1);
g.translate(-x, -y);
g.setColor(oldColor);
}
/**
* Return the amount of space taken up by a highlight border drawn by
* <code>drawHighlightBorder()</code>.
*
* @return The <code>Insets</code> needed for the highlight border.
* @see #drawHighlightBorder
*/
public static Insets getHighlightBorderInsets() {
return HIGHLIGHT_INSETS;
}
public static ImageIcon createImageIcon(Image image) {
if (image == null) {
return null;
}
synchronized (tracker) {
tracker.addImage(image, 0);
try {
tracker.waitForID(0, 0);
} catch (InterruptedException e) {
System.out.println("INTERRUPTED while loading Image");
}
tracker.removeImage(image, 0);
}
return new ImageIcon(image);
}
/**
* Returns a point where the given popup menu should be shown. The point is
* calculated by adjusting the X and Y coordinates from the given mouse
* event so that the popup menu will not be clipped by the screen
* boundaries.
*
* @param popup
* the popup menu
* @param event
* the mouse event
* @return the point where the popup menu should be shown
*/
public static Point getPopupMenuShowPoint(JPopupMenu popup, MouseEvent event) {
Component source = (Component) event.getSource();
Point topLeftSource = source.getLocationOnScreen();
Point ptRet = getPopupMenuShowPoint(popup,
topLeftSource.x + event.getX(), topLeftSource.y + event.getY());
ptRet.translate(-topLeftSource.x, -topLeftSource.y);
return ptRet;
}
/**
* Returns a point where the given popup menu should be shown. The point is
* calculated by adjusting the X and Y coordinates so that the popup menu
* will not be clipped by the screen boundaries.
*
* @param popup
* the popup menu
* @param x
* the x position in screen coordinate
* @param y
* the y position in screen coordinates
* @return the point where the popup menu should be shown in screen
* coordinates
*/
public static Point getPopupMenuShowPoint(JPopupMenu popup, int x, int y) {
Dimension sizeMenu = popup.getPreferredSize();
Point bottomRightMenu = new Point(x + sizeMenu.width, y
+ sizeMenu.height);
Rectangle[] screensBounds = getScreenBounds();
int n = screensBounds.length;
for (int i = 0; i < n; i++) {
Rectangle screenBounds = screensBounds[i];
if (screenBounds.x <= x
&& x <= (screenBounds.x + screenBounds.width)) {
Dimension sizeScreen = screenBounds.getSize();
sizeScreen.height -= 32; // Hack to help prevent menu being
// clipped by Windows/Linux/Solaris
// Taskbar.
int xOffset = 0;
if (bottomRightMenu.x > (screenBounds.x + sizeScreen.width))
xOffset = -sizeMenu.width;
int yOffset = 0;
if (bottomRightMenu.y > (screenBounds.y + sizeScreen.height))
yOffset = sizeScreen.height - bottomRightMenu.y;
return new Point(x + xOffset, y + yOffset);
}
}
return new Point(x, y); // ? that would mean that the top left point was
// not on any screen.
}
/**
* Centers the window over a component (usually another window). The window
* must already have been sized.
*
* @param window
* Window to center.
* @param over
* Component to center over.
*/
public static void centerWindowOnComponent(Window window, Component over) {
if ((over == null) || !over.isShowing()) {
centerWindowOnScreen(window);
return;
}
Point parentLocation = over.getLocationOnScreen();
Dimension parentSize = over.getSize();
Dimension size = window.getSize();
// Center it.
int x = parentLocation.x + (parentSize.width - size.width) / 2;
int y = parentLocation.y + (parentSize.height - size.height) / 2;
// Now, make sure it's onscreen
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
// This doesn't actually work on the Mac, where the screen
// doesn't necessarily start at 0,0
if (x + size.width > screenSize.width)
x = screenSize.width - size.width;
if (x < 0)
x = 0;
if (y + size.height > screenSize.height)
y = screenSize.height - size.height;
if (y < 0)
y = 0;
window.setLocation(x, y);
}
/**
* @param c
* Component to check on.
* @return returns true if the component of one of its child has the focus
*/
public static boolean isAncestorOfFocusedComponent(Component c) {
if (c.hasFocus()) {
return true;
} else {
if (c instanceof Container) {
Container cont = (Container) c;
int n = cont.getComponentCount();
for (int i = 0; i < n; i++) {
Component child = cont.getComponent(i);
if (isAncestorOfFocusedComponent(child))
return true;
}
}
}
return false;
}
/**
* Returns the first component in the tree of <code>c</code> that can accept
* the focus.
*
* @param c
* the root of the component hierarchy to search
* @param deepest
* if <code>deepest</code> is true the method will return the
* first and deepest component that can accept the focus. For
* example, if both a child and its parent are focusable and
* <code>deepest</code> is true, the child is returned.
* @see #focusComponentOrChild
* @return Component that was focused on.
*/
public static Component getFocusableComponentOrChild(Component c,
boolean deepest) {
if (c != null && c.isEnabled() && c.isVisible()) {
if (c instanceof Container) {
Container cont = (Container) c;
if (!deepest) { // first one is a good one
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
if (jc.isRequestFocusEnabled()) {
return jc;
}
}
}
int n = cont.getComponentCount();
for (int i = 0; i < n; i++) {
Component child = cont.getComponent(i);
Component focused = getFocusableComponentOrChild(child,
deepest);
if (focused != null) {
return focused;
}
}
if (c instanceof JComponent) {
if (deepest) {
JComponent jc = (JComponent) c;
if (jc.isRequestFocusEnabled()) {
return jc;
}
}
} else {
return c;
}
}
}
return null;
}
/**
* Puts the focus on the first component in the tree of <code>c</code> that
* can accept the focus.
*
* @see #getFocusableComponentOrChild
* @param c
* Component to focus on.
* @return Component that was focused on.
*/
public static Component focusComponentOrChild(Component c) {
return focusComponentOrChild(c, false);
}
/**
* Puts the focus on the first component in the tree of <code>c</code> that
* can accept the focus.
*
* @param c
* the root of the component hierarchy to search
* @param deepest
* if <code>deepest</code> is true the method will focus the
* first and deepest component that can accept the focus. For
* example, if both a child and its parent are focusable and
* <code>deepest</code> is true, the child is focused.
* @see #getFocusableComponentOrChild
* @return Component that was focused on.
*/
public static Component focusComponentOrChild(Component c, boolean deepest) {
final Component focusable = getFocusableComponentOrChild(c, deepest);
if (focusable != null) {
focusable.requestFocus();
}
return focusable;
}
/**
* Loads an {@link Image} named <code>imageName</code> as a resource
* relative to the Class <code>cls</code>. If the <code>Image</code> can not
* be loaded, then <code>null</code> is returned. Images loaded here will be
* added to an internal cache based upon the full {@link URL} to their
* location.
* <p/>
* <em>This method replaces legacy code from JDeveloper 3.x and earlier.</em>
*
* @see Class#getResource(String)
* @see Toolkit#createImage(URL)
* @param imageName
* Name of the resource to load.
* @param cls
* Class to pull resource from.
* @return Image loaded from resource.
*/
public static Image loadFromResource(String imageName, Class<?> cls) {
try {
final URL url = cls.getResource(imageName);
if (url == null) {
return null;
}
Image image = imageCache.get(url.toString());
if (image == null) {
image = Toolkit.getDefaultToolkit().createImage(url);
imageCache.put(url.toString(), image);
}
return image;
} catch (Exception e) {
}
return null;
}
public static Rectangle[] getScreenBounds() {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment
.getLocalGraphicsEnvironment();
final GraphicsDevice[] screenDevices = graphicsEnvironment
.getScreenDevices();
Rectangle[] screenBounds = new Rectangle[screenDevices.length];
for (int i = 0; i < screenDevices.length; i++) {
GraphicsDevice screenDevice = screenDevices[i];
final GraphicsConfiguration defaultConfiguration = screenDevice
.getDefaultConfiguration();
screenBounds[i] = defaultConfiguration.getBounds();
}
return screenBounds;
}
public static void makeSameSize(JComponent... comps) {
if (comps.length == 0) {
return;
}
int max = 0;
for (JComponent comp1 : comps) {
int w = comp1.getPreferredSize().width;
max = w > max ? w : max;
}
Dimension dim = new Dimension(max, comps[0].getPreferredSize().height);
for (JComponent comp : comps) {
comp.setPreferredSize(dim);
}
}
/**
* Return the hexidecimal color from a Color
*
* @param c
* Color to convert.
* @return hexadecimal string
*/
public static String toHTMLColor(Color c) {
int color = c.getRGB();
color |= 0xff000000;
String s = Integer.toHexString(color);
return s.substring(2);
}
public static String createToolTip(String text, int width) {
final String htmlColor = toHTMLColor(TOOLTIP_COLOR);
return "<html><table width=" + width + " bgColor=" + htmlColor
+ "><tr><td>" + text + "</td></tr></table></table>";
}
public static String createToolTip(String text) {
final String htmlColor = toHTMLColor(TOOLTIP_COLOR);
return "<html><table bgColor=" + htmlColor + "><tr><td>" + text
+ "</td></tr></table></table>";
}
public static String getHighlightedWords(String text, String query) {
final StringTokenizer tkn = new StringTokenizer(query, " ");
int tokenCount = tkn.countTokens();
String[] words = new String[tokenCount];
for (int j = 0; j < tokenCount; j++) {
String queryWord = tkn.nextToken();
words[j] = queryWord;
}
String highlightedWords;
try {
highlightedWords = StringUtils.highlightWords(text, words,
"<font style=background-color:yellow;font-weight:bold;>",
"</font>");
} catch (Exception e) {
highlightedWords = text;
}
return highlightedWords;
}
public static ImageIcon createShadowPicture(Image buf) {
buf = removeTransparency(buf);
BufferedImage splash;
JLabel label = new JLabel();
int width = buf.getWidth(null);
int height = buf.getHeight(null);
int extra = 4;
splash = new BufferedImage(width + extra, height + extra,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) splash.getGraphics();
BufferedImage shadow = new BufferedImage(width + extra, height + extra,
BufferedImage.TYPE_INT_ARGB);
Graphics g = shadow.getGraphics();
g.setColor(new Color(0.0f, 0.0f, 0.0f, 0.3f));
g.fillRoundRect(0, 0, width, height, 12, 12);
g2.drawImage(shadow, getBlurOp(7), 0, 0);
g2.drawImage(buf, 0, 0, label);
return new ImageIcon(splash);
}
public static BufferedImage removeTransparency(Image image) {
int w = image.getWidth(null);
int h = image.getHeight(null);
BufferedImage bi2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi2.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, w, h);
g.drawImage(image, 0, 0, null);
g.dispose();
return bi2;
}
public static Image toImage(BufferedImage bufferedImage) {
return Toolkit.getDefaultToolkit().createImage(
bufferedImage.getSource());
}
private static ConvolveOp getBlurOp(int size) {
float[] data = new float[size * size];
float value = 1 / (float) (size * size);
for (int i = 0; i < data.length; i++) {
data[i] = value;
}
return new ConvolveOp(new Kernel(size, size, data));
}
public static BufferedImage convert(Image im) throws InterruptedException,
IOException {
load(im);
BufferedImage bi = new BufferedImage(im.getWidth(null),
im.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}
public static void load(Image image) throws InterruptedException,
IOException {
MediaTracker tracker = new MediaTracker(new Label()); // any component
// will do
tracker.addImage(image, 0);
tracker.waitForID(0);
if (tracker.isErrorID(0))
throw new IOException("error loading image");
}
public static byte[] getBytesFromImage(Image image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(convert(image), "PNG", baos);
} catch (IOException e) {
} catch (InterruptedException e) {
}
return baos.toByteArray();
}
/**
* Returns a scaled down image if the height or width is smaller than the
* image size.
*
* @param icon
* the image icon.
* @param newHeight
* the preferred height.
* @param newWidth
* the preferred width.
* @return the icon.
*/
public static ImageIcon scaleImageIcon(ImageIcon icon, int newHeight,
int newWidth) {
Image img = icon.getImage();
int height = icon.getIconHeight();
int width = icon.getIconWidth();
if (height > newHeight) {
height = newHeight;
}
if (width > newWidth) {
width = newWidth;
}
img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);
return new ImageIcon(img);
}
/**
* Returns a scaled down image if the height or width is smaller than the
* image size.
*
* @param icon
* the image icon.
* @param newHeight
* the preferred height.
* @param newWidth
* the preferred width.
* @return the icon.
*/
public static ImageIcon scale(ImageIcon icon, int newHeight, int newWidth) {
Image img = icon.getImage();
img = img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
return new ImageIcon(img);
}
}