/* * Copyright (c) 2016, Metron, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Metron, Inc. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL METRON, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.metsci.glimpse.util; import static java.util.Collections.unmodifiableList; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; /** * This class holds miscellaneous static methods that are simple but broadly * useful. In particular, workarounds for Java defects can go here. * * @author hogye */ public class GeneralUtils { public static final String LINE_SEPARATOR = System.getProperty( "line.separator", "\n" ); /** * Prevent instantiation. */ private GeneralUtils( ) { } /** * Workaround for <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6480539">bug #6480539</a>: * BigDecimal.stripTrailingZeros() has no effect on zero itself ("0.0"). */ public static BigDecimal stripTrailingZeros( BigDecimal value ) { return ( value.compareTo( BigDecimal.ZERO ) == 0 ? BigDecimal.ZERO : value.stripTrailingZeros( ) ); } /** * Get standard Java hashCode for a long without the extra object creation. * * <p>Equivalent to (new Long(longVal)).hashCode() in jdk1.6.</p> * * @param longVal value for which to compute hashCode * @return hashCode */ public static int hashCode( long longVal ) { // combine upper 32 and lower 32 bits via exclusive or return ( int ) ( longVal ^ ( longVal >>> 32 ) ); } /** * Get standard Java hashCode for a float without the extra object creation. * * <p>Equivalent to (new Float(floatVal)).hashCode() in jdk1.6.</p> * * @param floatVal value for which to compute hashCode * @return hashCode */ public static int hashCode( float floatVal ) { return Float.floatToIntBits( floatVal ); } /** * Get standard Java hashCode for a float without the extra object creation. * * <p>Equivalent to (new Double(doubleVal)).hashCode() in jdk1.6.</p> * * @param doubleVal value for which to compute hashCode * @return hashCode */ public static int hashCode( double doubleVal ) { return hashCode( Double.doubleToLongBits( doubleVal ) ); } /** * Get standard Java hashCode for a boolean without the extra object creation. * * <p>Equivalent to (new Boolean(booleanVal)).hashCode() in jdk1.6.</p> * * @param booleanVal value for which to compute hashCode * @return hashCode */ public static int hashCode( boolean booleanVal ) { return ( booleanVal ? 1231 : 1237 ); } /** * Compare two shorts, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param shortVal1 * @param shortVal2 * @return -1, 0, or 1 if shortVal1 is less than, equal to, or greater than shortVal2 respectively. */ public static short compare( short shortVal1, short shortVal2 ) { return compareShorts( shortVal1, shortVal2 ); } /** * Compare two shorts, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param shortVal1 * @param shortVal2 * @return -1, 0, or 1 if shortVal1 is less than, equal to, or greater than shortVal2 respectively. */ public static short compareShorts( short shortVal1, short shortVal2 ) { if ( shortVal1 < shortVal2 ) { return -1; } else if ( shortVal1 > shortVal2 ) { return 1; } return 0; } /** * Compare two ints, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param intVal1 * @param intVal2 * @return -1, 0, or 1 if intVal1 is less than, equal to, or greater than intVal2 respectively. */ public static int compare( int intVal1, int intVal2 ) { return compareInts( intVal1, intVal2 ); } /** * Compare two ints, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param intVal1 * @param intVal2 * @return -1, 0, or 1 if intVal1 is less than, equal to, or greater than intVal2 respectively. */ public static int compareInts( int intVal1, int intVal2 ) { if ( intVal1 < intVal2 ) { return -1; } else if ( intVal1 > intVal2 ) { return 1; } return 0; } /** * Compare two longs, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param longVal1 * @param longVal2 * @return -1, 0, or 1 if longVal1 is less than, equal to, or greater than longVal2 * respectively. */ public static int compare( long longVal1, long longVal2 ) { return compareLongs( longVal1, longVal2 ); } /** * Compare two longs, according to the standard Comparable interface. Since 1.4, the JDK provides * Double.compare( double, double ) and Float.compare( float, float ) but not variants for * Integer, Long, and Short. * * @param longVal1 * @param longVal2 * @return -1, 0, or 1 if longVal1 is less than, equal to, or greater than longVal2 * respectively. */ public static int compareLongs( long longVal1, long longVal2 ) { if ( longVal1 < longVal2 ) { return -1; } else if ( longVal1 > longVal2 ) { return 1; } return 0; } /** * This method returns the correct type as specified by the caller, unlike {@link Class#forName(String)}. * It also helps localizing the "Type safety" warnings to a single place. */ public static <T> Class<? extends T> classForName( String className ) throws ClassNotFoundException { return GeneralUtils.cast( Class.forName( className ) ); } /** * Returns the directory in which the application was started (this is the * working/current directory). */ public static String getWorkingDir( ) { return System.getProperty( "user.dir" ); } /** * Type casts from one type to another. Provided mostly to reduce the number * of "type safety" warnings.<br><br> * * NOTE: When using the Sun Java compiler, this method should be invoked as GeneralUtils.< T, U >cast(u) * to avoid the following <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954">bug</a>. */ @SuppressWarnings( "unchecked" ) public static <T, U> T cast( U u ) { return ( T ) u; } /** * Creates a new {@link HashSet} by examining the expected return type. */ public static final <K> HashSet<K> newHashSet( ) { return new HashSet<K>( ); } /** * Creates a new {@link HashSet} containing the elements of the specified * collection. * * @see {@link HashSet#HashSet(Collection)} */ public static final <K> HashSet<K> newHashSet( Collection<? extends K> c ) { return new HashSet<K>( c ); } /** * Creates a new {@link LinkedHashSet} by examining the expected return type. */ public static final <K> LinkedHashSet<K> newLinkedHashSet( ) { return new LinkedHashSet<K>( ); } /** * Creates a new {@link LinkedHashSet} containing the elements of the specified * collection. * * @see {@link LinkedHashSet#LinkedHashSet(Collection)} */ public static final <K> LinkedHashSet<K> newLinkedHashSet( Collection<? extends K> c ) { return new LinkedHashSet<K>( c ); } /** * Creates a new {@link TreeSet} by examining the expected return type. */ public static final <K> TreeSet<K> newTreeSet( ) { return new TreeSet<K>( ); } /** * Creates a new {@link HashMap} by examining the expected return type. */ public static final <K, V> HashMap<K, V> newHashMap( ) { return new HashMap<K, V>( ); } /** * Creates a new {@link HashMap} containing the same mappings as the * specified map. * * @see {@link HashMap#HashMap(Map)} */ public static final <K, V> HashMap<K, V> newHashMap( Map<? extends K, ? extends V> m ) { return new HashMap<K, V>( m ); } /** * Creates a new {@link LinkedHashMap} by examining the expected return type. */ public static final <K, V> LinkedHashMap<K, V> newLinkedHashMap( ) { return new LinkedHashMap<K, V>( ); } /** * Creates a new {@link TreeMap} by examining the expected return type. */ public static final <K, V> TreeMap<K, V> newTreeMap( ) { return new TreeMap<K, V>( ); } /** * Creates a new {@link ArrayList} by examining the expected return type. */ public static final <K> ArrayList<K> newArrayList( ) { return new ArrayList<K>( ); } /** * Creates a new {@link ArrayList} containing the elements of the specified * collection, in order. * * @see {@link ArrayList#ArrayList(Collection)}. */ public static final <K> ArrayList<K> newArrayList( Collection<? extends K> c ) { return new ArrayList<K>( c ); } /** * Creates a new unmodifiable {@link List} containing the elements of the * specified collection, in order. */ public static final <K> List<K> newUnmodifiableList( Collection<? extends K> c ) { return unmodifiableList( newArrayList( c ) ); } /** * Creates a new {@link ArrayList} from a collection by building an * enumeration over the collection. */ public static final <K> ArrayList<K> asList( Collection<K> values ) { return Collections.list( Collections.<K> enumeration( values ) ); } @SuppressWarnings( "unchecked" ) public static final <K> HashSet<K> asSet( K... values ) { return new HashSet<K>( Arrays.asList( values ) ); } /** * Terse (especially as a static import) way to create an int[] literal. */ public static int[] ints( int... values ) { return values; } /** * Terse (especially as a static import) way to create a long[] literal. */ public static long[] longs( long... values ) { return values; } /** * Terse (especially as a static import) way to create a float[] literal. */ public static float[] floats( float... values ) { return values; } /** * Terse (especially as a static import) way to create a double[] literal. */ public static double[] doubles( double... values ) { return values; } /** * Terse (especially as a static import) way to create a boolean[] literal. */ public static boolean[] booleans( boolean... values ) { return values; } /** * Terse (especially as a static import) way to create a T[] literal. */ @SuppressWarnings( "unchecked" ) public static <T> T[] array( T... values ) { return values; } /** * Terse (especially as a static import) way to create an EnumSet. */ @SuppressWarnings( "unchecked" ) public static <T extends Enum<T>> EnumSet<T> enumSet( T... elements ) { return EnumSet.<T> of( elements[0], elements ); } /** * Convenience method for formatting and appending data to an existing StringBuffer. */ public static void stringBufferAppend( StringBuffer sb, String format, Object... args ) { sb.append( String.format( format, args ) ); } /** * Convenience method for formatting and appending data to an existing StringBuilder. */ public static void stringBuilderAppend( StringBuilder sb, String format, Object... args ) { sb.append( String.format( format, args ) ); } }