/******************************************************************************* * Copyright 2012 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.common.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * Utility class containing general helper methods. */ public class Util { private Util() { } private static final Map<Class<?>, Class<?>> primitiveToBoxed; private static final Map<Class<?>, Class<?>> boxedToPrimitive; static { Map<Class<?>, Class<?>> ptb = new HashMap<Class<?>, Class<?>>(); ptb.put(int.class, Integer.class); ptb.put(boolean.class, Boolean.class); ptb.put(long.class, Long.class); ptb.put(char.class, Character.class); ptb.put(byte.class, Byte.class); ptb.put(double.class, Double.class); ptb.put(float.class, Float.class); ptb.put(short.class, Short.class); primitiveToBoxed = Collections.unmodifiableMap(ptb); Map<Class<?>, Class<?>> btp = new HashMap<Class<?>, Class<?>>(); for (Entry<Class<?>, Class<?>> entry : ptb.entrySet()) { btp.put(entry.getValue(), entry.getKey()); } boxedToPrimitive = Collections.unmodifiableMap(btp); } /** * Convert the given primitive class (int.class, long.class, etc) to its * boxed version (Integer.class, Long.class, etc). Returns null if the given * class is not a primitive class. * * @param primitiveClass * @return Boxed version of the given primitive class */ public static Class<?> primitiveClassToBoxed(Class<?> primitiveClass) { return primitiveToBoxed.get(primitiveClass); } /** * Convert the given boxed class (Integer.class, Long.class, etc) to its * primitive version (int.class, long.class, etc). Returns null if the given * class is not a boxed class. * * @param boxedClass * @return Primitive version of the given boxed class, or null */ public static Class<?> boxedClassToPrimitive(Class<?> boxedClass) { return boxedToPrimitive.get(boxedClass); } /** * Split a string using the provided separator, then convert the split * components to ints. * * @param string * @param separator * @return Array of ints parsed from the string. */ public static int[] splitInts(String string, String separator) { String[] split = string.trim().split(separator); List<Integer> ints = new ArrayList<Integer>(split.length); for (String s : split) { try { ints.add(Integer.valueOf(s.trim())); } catch (Exception e) { } } int[] is = new int[ints.size()]; for (int i = 0; i < is.length; i++) { is[i] = ints.get(i); } return is; } /** * Concatenate an array of ints into a single string, separated by the * provided separator. * * @param array * @param separator * @return Concatenated ints as a string. */ public static String concatInts(int[] array, String separator) { if (array == null || array.length == 0) { return ""; //$NON-NLS-1$ } if (separator == null) { separator = ""; //$NON-NLS-1$ } StringBuilder sb = new StringBuilder(); for (int i : array) { sb.append(separator); sb.append(i); } return sb.substring(separator.length()); } /** * Concatenate an array of objects in a single string, separated by the * provided separator. * <p/> * If an object is <code>null</code>, the provided {@code nullValue} will be * used. * * @param array * The array of values to concatenate * @param separator * The separator to use when concatenating * @param nullValue * The value to use in the case of a null element * * @return The concatenated string */ public static String concat(Object[] array, String separator, String nullValue) { if (array == null || array.length == 0) { return ""; //$NON-NLS-1$ } if (separator == null) { separator = ""; //$NON-NLS-1$ } StringBuilder sb = new StringBuilder(); for (Object o : array) { sb.append(separator); sb.append(o == null ? nullValue : o.toString()); } return sb.substring(separator.length()); } /** * Is the given string empty (null, or of length 0)? * * @param s * String to check if empty. * @return True if the given string is empty. */ public static boolean isEmpty(String s) { return s == null || s.length() == 0; } /** * Returns a blank string if the given string is null, otherwise returns the * string. * * @param s * @return Blank string if <code>s</code> is null, otherwise <code>s</code> */ public static String blankNullString(String s) { return s == null ? "" : s; //$NON-NLS-1$ } /** * Remove all whitespace from the given string * * @param s * @return The input string with all whitespace removed */ public static String removeWhitespace(String s) { return s == null ? null : s.replaceAll("\\s*", ""); //$NON-NLS-1$//$NON-NLS-2$ } /** * Perform a null-safe equality test on the two provided objects * * @return <code>true</code> if both objects are equal according to * {@link Object#equals(Object)}, or if both objects are * <code>null</code>. */ public static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) { return true; } if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) { return false; } return o1.equals(o2); } /** * Call the given named property's setter on the object with an Object * represented by the propertyValue string. The property's setter's * parameter count must be 1, and the parameter class must be * {@link StringInstantiable#isInstantiable(Class)}. * * @param o * Object on which to call the setter * @param propertyName * Name of the property to set * @param propertyValue * {@link StringInstantiable} representation of the property * value * @return True if the setter method was found and invoked without error, * false otherwise * @throws InvocationTargetException * If an exception was raised while invoking the setter */ public static boolean setPropertyOn(Object o, String propertyName, String propertyValue) throws InvocationTargetException { if (isEmpty(propertyName)) { throw new IllegalArgumentException("Property name is empty"); //$NON-NLS-1$ } String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); //$NON-NLS-1$ Method[] methods = o.getClass().getMethods(); for (Method method : methods) { if (method.getName().equals(methodName) && method.getParameterTypes().length == 1) { Class<?> type = method.getParameterTypes()[0]; if (StringInstantiable.isInstantiable(type)) { Object value = StringInstantiable.newInstance(propertyValue, type); if (value != null) { try { method.invoke(o, value); return true; } catch (InvocationTargetException e) { throw e; } catch (Exception e) { } } } } } return false; } /** * Save the given InputStream to a temporary file. Uses the * {@link File#createTempFile(String, String)} method to generate the file. * * @param is * InputStream to save * @param prefix * Prefix to use for the filename; must be at least 3 characters * @param suffix * Suffix to use for the filename; if null, <code>.tmp</code> is * used * @return File containing the contents of the InputStream * @throws IOException * If writing fails */ public static File writeInputStreamToTemporaryFile(InputStream is, String prefix, String suffix) throws IOException { File file = File.createTempFile(prefix, suffix); file.deleteOnExit(); FileOutputStream fos = null; try { fos = new FileOutputStream(file); writeInputStreamToOutputStream(is, fos); } finally { if (fos != null) { fos.close(); } } return file; } /** * Write the given InputStream to the given OutputStream, until no bytes are * left in the InputStream. Uses a buffer size of 8096 bytes. * * @param is * InputStream to read from * @param os * OutputStream to write to * @throws IOException * If writing fails */ public static void writeInputStreamToOutputStream(InputStream is, OutputStream os) throws IOException { writeInputStreamToOutputStream(is, os, 8096); } /** * Write the given InputStream to the given OutputStream, until no bytes are * left in the InputStream. * * @param is * InputStream to read from * @param os * OutputStream to write to * @param bufferSize * Size of the intermediate buffer * @throws IOException * If writing fails */ public static void writeInputStreamToOutputStream(InputStream is, OutputStream os, int bufferSize) throws IOException { byte[] buffer = new byte[bufferSize]; int len; while ((len = is.read(buffer)) >= 0) { os.write(buffer, 0, len); } } /** * Read the file extension from the given string. This is defined as the * string including and after the last '.' dot (eg * <code>temp/file.txt</code> = <code>.txt</code>). * <p/> * Returns null for a null path, or an empty string if no extension can be * found or the extension contains non-word characters [a-zA-Z_0-9]. * * * @param path * Path to determine the file extension for * @return File extension for path */ public static String getExtension(String path) { if (path == null) { return null; } int lastIndexOfDot = path.lastIndexOf('.'); int lastIndexOfSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')); if (lastIndexOfDot > lastIndexOfSlash) { String extension = path.substring(lastIndexOfDot); if (extension.matches("\\w+")) //$NON-NLS-1$ { return extension; } } return ""; //$NON-NLS-1$ } /** * Read the given stream until EOF, and return a string. * * @param stream * Stream to read * @param charsetName * Charset to read the stream in * @return String read from stream * @throws IOException * If an IO error occurs during read */ public static String readStreamToString(InputStream stream, String charsetName) throws IOException { StringBuilder sb = new StringBuilder(); byte[] buffer = new byte[8192]; int read; while ((read = stream.read(buffer)) >= 0) { String s = new String(buffer, 0, read, charsetName); sb.append(s); } return sb.toString(); } /** * Search through the text, and replace all instances of a character with a * string. * * @param text * Text to replace characters within * @param c * Character to replace * @param s * String to replace characters with * @return Text with all <code>c</code> characters replaced with * <code>s</code> */ public static String replace(String text, char c, String s) { int previous = 0; int current = text.indexOf(c, previous); if (current == -1) { return text; } StringBuilder sb = new StringBuilder(); while (current > -1) { sb.append(text.substring(previous, current)); sb.append(s); previous = current + 1; current = text.indexOf(c, previous); } sb.append(text.substring(previous)); return sb.toString(); } }