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

com.jsftoolkit.utils.Utils Maven / Gradle / Ivy

Go to download

The core classes for the JSF Toolkit Component Framework. Includes all framework base and utility classes as well as component kick-start/code-generation and registration tools. Also includes some classes for testing that are reused in other projects. They cannot be factored out into a separate project because they are referenced by the tests and they reference this code (circular dependence).

The newest version!
package com.jsftoolkit.utils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;

/**
 * Utility functions. We reinvent the wheel here because we want to avoid
 * requiring external dependencies.
 * 

* See the unit tests for further examples of usage. Methods that are not unit * tested are noted. * * @author noah * */ public class Utils { /** * Base class for iterators that do not support remove. * * @author noah * * @param */ public static abstract class StaticIterator implements Iterator { public final void remove() { throw new UnsupportedOperationException(); } } /** * * @param * @param value * @param def * @return def, if value is null. Otherwise, value. */ public static T getValue(T value, T def) { return value == null ? def : value; } /** * Similar to {@link #getValue(Object, Object)}, but allows both return * values to be specified. * * @param * @param obj * @param isNull * returned if obj is null * @param isntNull * returned if obj is not null * @return isNull or isntNull */ public static T getValue(Object obj, T isNull, T isntNull) { return obj == null ? isNull : isntNull; } /** * Gets the value of the given key from the map, and if it is not null * returns it. Otherwise returns def. * * @param * @param * @param map * @param key * @param def * @return */ public static V getValue(Map map, K key, V def) { return getValue(map.get(key), def); } /** * Checks map for the given key, setting it to the given default if the * value returned is null. * * @param * @param * @param map * @param key * @param def * @return the value in the map. */ public static V mapDefault(Map map, K key, V def) { V v = map.get(key); if (v == null) { map.put(key, def); v = def; } return v; } /** * * @param s * @param def * the default value * @return s if s is not empty according to {@link #isEmpty(String)}, * otherwise def */ public static String getValue(String s, String def) { return isEmpty(s) ? def : s; } public static boolean isEmpty(Object o) { return isEmpty(Utils.toString(o)); } /** * * @param s * @return true if s is null or contains only whitespace characters * according to {@link Character#isWhitespace(char)}. Otherwise, * false. */ public static boolean isEmpty(CharSequence s) { if (s != null) { for (int i = 0; i < s.length(); i++) { if (!Character.isWhitespace(s.charAt(i))) { return false; } } } return true; } /** * Same as join(array, del, 0, array.length) * * @param array * @param del * @return */ public static String join(final Object[] array, Object del) { return array == null ? "" : join(array, del, 0, array.length); } /** * Joins the given array by creating an * {@link #arrayIterator(Object[], int, int)} and passing it to * {@link #join(Iterator, Object)} * * @param array * @param del * @param startIndex * 0 to array.length * @param length * number of element to return * @return */ public static String join(final Object[] array, Object del, final int startIndex, final int length) { return join(arrayIterator(array, startIndex, length), del); } /** * Factory for iterators over a particular array. Simply delegates to * {@link Utils#arrayIterator(Object[], int, int)}. * * @author noah * * @param */ public static class ArrayIterable implements Iterable { private final T[] array; private final int startIndex; private final int length; /** * * @see Utils#arrayIterator(Object[], int, int) */ public ArrayIterable(final T[] array, final int startIndex, final int length) { super(); this.array = array; this.startIndex = startIndex; this.length = length; } /** * @see Utils#arrayIterator(Object[], int, int) */ public Iterator iterator() { return arrayIterator(array, startIndex, length); } /** * @see Utils#arrayIterator(Object[], int, int) */ public static Iterable iterable(T[] array, int startIndex, int length) { return new ArrayIterable(array, startIndex, length); } } /** * * @param * @param array * the elements t iterate over. * @return an iterator over the given elements. */ public static Iterator arrayIterator(final T... array) { return arrayIterator(array, 0, array.length); } /** * Creates an iterator that returns elements from the given array. If length < * 0, the iterator will traverse backwards from startIndex(inclusive), * returning a total of length elements. Array indecies that go above * array.length or below 0 are wrapped according to the semantics of * {@link #wrap(int, int)} e.g. *

* array = {"foo","bar","baz"}
* elements of arrayIterator(array,0,3) = "foo","bar","baz"
* elements of arrayIterator(array,3,0) = empty
* elements of arrayIterator(array,1,2) = "bar","baz"
* elements of arrayIterator(array,1,1) = "bar"
* elements of arrayIterator(array,1,-1) = "bar"
* elements of arrayIterator(array,1,-2) = "bar","foo"
* elements of arrayIterator(array,3,-2) = "foo","baz"
* elements of arrayIterator(array,-1,-2) = "baz","bar"
* elements of arrayIterator(array,-1,-5) = "baz","bar","foo","baz","bar" *
* * @param * @param array * @param startIndex * @param length * @return */ public static Iterator arrayIterator(final T[] array, final int startIndex, final int length) { if (length < 0) { return new StaticIterator() { int i = wrap(startIndex, array.length); int remaining = array.length > 0 ? -length : 0; public boolean hasNext() { return remaining > 0; } public T next() { T t = array[i]; i = wrap(i - 1, array.length); remaining--; return t; } }; } return new StaticIterator() { int i = wrap(startIndex, array.length); int remaining = array.length > 0 ? length : 0; public boolean hasNext() { return remaining > 0; } public T next() { T t = array[i]; i = wrap(i + 1, array.length); remaining--; return t; } }; } /** * Wraps values with modulo arithmetic. Negative values are considered * offsets from top. e.g. -1 wraps to top - 1. -top wraps to 0. top + 1 * wraps to 1. If top <= 0, returns 0. * * @param value * @param top * @return a number between 0 (inclusive) and top (exclusive) */ public static int wrap(int value, int top) { if (top <= 0) { return 0; } value %= top; return value < 0 ? top + value : value; } /** * Concatenates the {@link Object#toString()} of elements from it, appending * del between elements. e.g. joining "foo","bar","baz" with del "," = * "foo,bar,baz" * * @param it * @param del * @return */ public static String join(Iterator it, Object del) { StringBuilder sb = new StringBuilder(); if (it.hasNext()) { sb.append(it.next()); while (it.hasNext()) { sb.append(del); sb.append(it.next()); } } return sb.toString(); } /** * {@link #toString(Object)}'s object and calls split on it. * * @param object * @param del * @return */ public static String[] split(Object object, String del) { return split(object, del, 0); } /** * * @param object * @param del * @param limit * same as {@link String#split(String, int)} * @return */ public static String[] split(Object object, String del, int limit) { return toString(object).split(del, limit); } /** * * @param obj * @return the {@link Object#toString()} of obj if it is not null, or the * empty string otherwise. */ public static String toString(Object obj) { return toString(obj, ""); } /** * * @param obj * @param def * @return the {@link Object#toString()} if obj is not null, def otherwise. */ public static String toString(Object obj, String def) { return obj == null ? def : obj.toString(); } /** * Finds a method on the given class that would accept parameters of the * given types and has the given return type (if specified). * * @param clazz * @param returnType * the return type of the method, or null if it doesn't matter. * @param paramTypes * the types of the parameters to be passed. * @return the {@link Method}, if found. */ public static Method findMethod(Class clazz, Class returnType, Class... paramTypes) { Method[] methods = clazz.getMethods(); methodLoop: for (Method method : methods) { Class[] types = method.getParameterTypes(); if (types.length == paramTypes.length && (returnType == null || method.getReturnType() .isAssignableFrom(returnType))) { for (int i = 0; i < types.length; i++) { if (!types[i].isAssignableFrom(paramTypes[i])) { continue methodLoop; } } return method; } } return null; } /** * null safe version of {@link #findMethod(Class, Class, Class[])}. If * object is null, returns null, otherwise calls * {@link #findMethod(Class, Class, Class[])} with object.getClass(). * * @param object * @param returnType * @param paramTypes * @return */ public static Method findMethod(Object object, Class returnType, Class... paramTypes) { return object == null ? null : findMethod(object.getClass(), returnType, paramTypes); } /** * Gets the specified index from the list if the list is not null and index * < list.size(). Otherwise returns null. * * @param * @param list * @param index * @return */ public static T get(List list, int index) { if (list != null && list.size() > index) { return list.get(index); } return null; } /** * Null safe equals. o1 and o2 may be null. If o1 and o2 are null, returns * true. * * @param o1 * @param o2 * @return */ public static boolean equals(Object o1, Object o2) { if (o1 == o2) { return true; } return o1 != null && o1.equals(o2); } /** * Loads a class path resource as an {@link InputStream} and calls * {@link #toString(InputStream, String)}. * * @param resource * @param encoding * @return * @throws IOException * if resource is not found. */ public static String resourceToString(String resource, String encoding) throws IOException { InputStream stream = Utils.class.getResourceAsStream(resource); if (stream == null) { throw new FileNotFoundException(resource); } return toString(stream, encoding); } /** * Similar to {@link #resourceToString(String, String)}, but returns a * default value if anything goes wrong (file not found, couldn't be read, * etc.) * * @param resource * @param encoding * @param def * the default value * @return */ public static String resourceToString(String resource, String encoding, String def) { try { return resourceToString(resource, encoding); } catch (IOException e) { return def; } } /** * Reads the given stream in the given encoding, into a String. * * @param in * @param encoding * @return * @throws IOException */ public static String toString(InputStream in, String encoding) throws IOException { return toString(new InputStreamReader(in, getCharset(encoding))); } /** * Converts the given bytes into a string. If encoding is null, the platform * default is used. * * @param bytes * @param encoding * @return * @throws UnsupportedEncodingException */ public static String toString(byte[] bytes, String encoding) throws UnsupportedEncodingException { return encoding == null ? new String(bytes) : new String(bytes, encoding); } /** * Reads all the characters and returns them as a string. * * @param reader * @return * @throws IOException */ public static String toString(Reader reader) throws IOException { StringWriter writer = new StringWriter(); writeAll(reader, writer); return writer.toString(); } /** * Gets the supported charset with the given name, returning the default * charset if the named charset is null or not supported. * * @param charsetName * @return */ public static Charset getCharset(String charsetName) { return charsetName != null && Charset.isSupported(charsetName) ? Charset .forName(charsetName) : Charset.defaultCharset(); } /** * Size of default byte and char buffers. */ private static final int BUFFER_SIZE = 16384; /** * Copies characters from the given reader to the give writter until the * reader returns EOS. * * @param in * @param out * @throws IOException */ public static void writeAll(Reader in, Writer out) throws IOException { writeAll(in, out, new char[BUFFER_SIZE]); } /** * Same as {@link #writeAll(Reader, Writer)}, but uses the given buffer. * * @param in * @param out * @param b * @throws IOException */ public static void writeAll(Reader in, Writer out, char[] b) throws IOException { int read; while ((read = in.read(b)) != -1) { out.write(b, 0, read); } } /** * Copies all the bytes from in to out, using the given buffer. * * @param in * @param out * @param b * @throws IOException */ public static void writeAll(InputStream in, OutputStream out, byte[] b) throws IOException { int read; while ((read = in.read(b)) != -1) { out.write(b, 0, read); } } /** * Same as {@link #writeAll(InputStream, OutputStream, byte[])}, but uses a * buffer of the default size. * * @param in * @param out * @throws IOException */ public static void writeAll(InputStream in, OutputStream out) throws IOException { writeAll(in, out, new byte[BUFFER_SIZE]); } /** * * @param string * @return string, with the first char in uppercase. */ public static String capitalize(String string) { return string != null && string.length() > 0 ? Character .toUpperCase(string.charAt(0)) + string.substring(1) : ""; } /** * * @param string * @return string, with the first character lowercase. */ public static String uncapitalize(String string) { return string != null && string.length() > 0 ? Character .toLowerCase(string.charAt(0)) + string.substring(1) : ""; } /** * Concatenates the two 'arrays', returning the new array. * * @param array * @param append * @return */ @SuppressWarnings("unchecked") public static String[] append(String[] array, String... append) { return doAppend(new String[array.length + append.length], array, append); } public static Object[] append(Object[] array, Object... append) { return doAppend(new Object[array.length + append.length], array, append); } private static T[] doAppend(T[] _new, T[] array, T[] append) { System.arraycopy(array, 0, _new, 0, array.length); System.arraycopy(append, 0, _new, array.length, append.length); return _new; } /** * Gets the value of the named property via introspection. * * @param * @param obj * @param property * @return * @throws IntrospectionException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InvocationTargetException */ @SuppressWarnings("unchecked") public static T getProperty(Object obj, String property) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { PropertyDescriptor pd = new PropertyDescriptor(property, obj.getClass()); return (T) pd.getReadMethod().invoke(obj); } /** * same as get(array, index, null) * * @param * @param array * @param index * @return */ public static T get(T[] array, int index) { return get(array, index, null); } /** * Gets the given array index, if it exists, otherwise returns def. * * @param * @param array * @param index * @param def * @return */ public static T get(T[] array, int index, T def) { return array != null && index < array.length ? array[index] : def; } /** * Creates a new set from the given items, the order they are given will be * their iteration order. * * @param * @param items * @return */ public static LinkedHashSet asSet(T... items) { LinkedHashSet set = new LinkedHashSet(); if (items != null) { for (T item : items) { set.add(item); } } return set; } /** * Collects the values of the map associated with the given keys into a set. * * @param * @param * @param map * @param keys * @return */ public static Set getValues(Map map, Iterator keys) { Set values = new HashSet(); while (keys.hasNext()) { values.add(map.get(keys.next())); } return values; } /** * Fills the given array with the given value. * * @param array * @param value * @return array */ public static boolean[] fill(boolean[] array, boolean value) { Arrays.fill(array, value); return array; } /** * Fills the given array with the given value. * * @param array * @param value * @return array */ public static T[] fill(T[] array, T value) { Arrays.fill(array, value); return array; } /** * Casts the given ints down to bytes. * * @param bytes * @return */ public static byte[] truncate(int[] bytes) { byte[] array = new byte[bytes.length]; for (int i = 0; i < array.length; i++) { array[i] = (byte) bytes[i]; } return array; } /** * Casts the given ints to chars. * * @param chars * @return */ public static char[] toCharArray(int[] chars) { char[] array = new char[chars.length]; for (int i = 0; i < array.length; i++) { array[i] = (char) chars[i]; } return array; } /** * Set the array index to true, returning array. For chaining. Untested. * * @param array * @param index * @return */ public static boolean[] set(boolean[] array, int index) { array[index] = true; return array; } /** * Set the array index to false, returning array. For chaining. Untested. * * @param array * @param index * @return */ public static boolean[] unset(boolean[] array, int index) { array[index] = false; return array; } /** * Utility class for chaining put operations on map. * * @author noah * * @param * @param */ public static class MapBuilder { private final Map map; public MapBuilder(Map map) { super(); this.map = map; } public MapBuilder put(K key, V value) { map.put(key, value); return this; } public Map getMap() { return map; } public static MapBuilder putFirst(K key, V value) { return new MapBuilder(new HashMap()).put(key, value); } } /** * * @param array * @return an array with null elements removed. */ public static Object[] prune(Object[] array) { List list = new ArrayList(array.length); for (Object o : array) { if (o != null) { list.add(o); } } return list.toArray(); } /** * * @param array * @return a new array with the empty strings removed */ public static String[] prune(String[] array) { List list = new ArrayList(array.length); for (String o : array) { if (!Utils.isEmpty(o)) { list.add(o); } } return list.toArray(new String[list.size()]); } /** * * @param obj * @return a string representing the given object. e.g. "null" if it is * null, or ""Objects's toString"" (i.e. a quoted literal) */ public static String toStringConstant(Object obj) { return obj == null ? "null" : "\"" + toString(obj).replaceAll("\"", "\\\"") .replaceAll("\n", "\\n") + "\""; } /** * * @param array * @return */ public static String toStringConstantArray(Object... array) { StringBuilder sb = new StringBuilder("{ "); if (array != null && array.length > 0) { sb.append(toStringConstant(array[0])); for (int i = 1; i < array.length; i++) { sb.append(", ").append(toStringConstant(array[i])); } } sb.append(" }"); return sb.toString(); } /** * Converts a camelCase name to a constant name, e.g. camelCase -> * CAMEL_CASE. Non-alphanumeric ( as defined by * {@link Character#isLetterOrDigit(char)}) characters are also converted * to underscores. * * @param name * @return */ public static String toConstantName(CharSequence name) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < name.length(); i++) { char ch = name.charAt(i); if (Character.isUpperCase(ch)) { sb.append('_'); } sb.append(Character.isLetterOrDigit(ch) ? Character.toUpperCase(ch) : '_'); } return sb.toString(); } /** * Throws a {@link NullPointerException} if value is null. * * @param value * @param message * @throws NullPointerException */ public static void notNull(Object value, String message) throws NullPointerException { if (value == null) { throw new NullPointerException(message); } } /** * Throws an {@link IllegalArgumentException} with the given message if * string is empty. * * @param string * @param message */ public static void notEmpty(CharSequence string, String message) { if (isEmpty(string)) { throw new IllegalArgumentException(message); } } /** * Puts the elements of it into a list. Untested. * * @param * @param it * @return */ public static List asList(Iterator it) { List list = new ArrayList(); while (it.hasNext()) { list.add(it.next()); } return list; } public static void write(Document document, OutputStream out) throws IOException, ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException { DOMImplementationLS impl = (DOMImplementationLS) DOMImplementationRegistry .newInstance().getDOMImplementation("LS"); if (impl == null) { final String serializer = "com.sun.org.apache.xml.internal.serialize.XMLSerializer"; final String format = "com.sun.org.apache.xml.internal.serialize.OutputFormat"; try { Object instance = ClassUtils.instantiate(serializer, out, ClassUtils.instantiate(format, document, null, true)); ClassUtils.invoke(instance, "serialize", document); } catch (InvocationTargetException e) { throw new ClassNotFoundException(serializer + " is not available."); } } else { LSOutput output = impl.createLSOutput(); output.setByteStream(out); impl.createLSSerializer().write(document, output); } } public static boolean createFileAndParents(final File file) throws IOException, SecurityException { if (file.exists()) { return true; } if (file.getParentFile().exists() || file.getParentFile().mkdirs()) { return file.createNewFile(); } return false; } public static class CreateFileException extends IOException { private static final long serialVersionUID = 1L; private Throwable cause; public CreateFileException(String message, Throwable cause) { super(message); this.cause = cause; } @Override public Throwable getCause() { return cause; } } public static String xmlEscape(String string) { return Utils.toString(string).replaceAll("&", "&").replaceAll("<", "<"); } public static String xmlAttribEscape(String string) { return xmlEscape(string).replaceAll("\"", """); } public static String[][] doubleSplit(String string, String del1, String del2, int limit1, int limit2) { String[] split = split(string, del1, limit1); String[][] matrix = new String[split.length][]; int i = 0; for (String item : split) { matrix[i++] = item.split(del2, limit2); } return matrix; } /** * * @param keyValues * @return */ public static Map asMap(String[][] keyValues) { Map map = new HashMap(); for (String[] pair : keyValues) { map.put(get(pair, 0), get(pair, 1)); } return map; } public static int getInt(String number, int def) { try { return Integer.parseInt(number); } catch (NumberFormatException e) { return def; } } }