Update of /cvsroot/displaytag/table-ben/src/com/tablelib/core/lang
In directory sc8-pr-cvs1:/tmp/cvs-serv11524

Added Files:
        ArrayUtils.java CaseInsensitiveStringAndNumberComparator.java 
        LongUtils.java NumberUtils.java StringUtils.java 
Log Message:


--- NEW FILE: ArrayUtils.java ---
/**
 * Created by IntelliJ IDEA.
 * User: Benjamin Simpson
 * Date: Jan 11, 2003
 * Time: 8:44:51 PM
 */

package com.tablelib.core.lang;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public final class ArrayUtils {

    private static final Class[] NO_CLASSES = new Class[0];

    /**
     * for each element in the array,
     * @param values
     * @param indexes
     */
    private static void reorder(Object[] values, int[] indexes) {
        int length = indexes.length;
        Object[] newvalues = new Object[length];
        for (int i = 0; i < length; i++) {
            newvalues[i] = values[indexes[i]];
        }
        System.arraycopy(newvalues, 0, values, 0, length);
    }


    /**
     * Why would you use this class.method?
     * An object [] contains a value that you are interested in.  The normal path
     * to getting an array of the values would be:
     * <ul>
     *      <li>Get the array
     *       <li>create another array
     *       <li>for each element in the array get the element's value
     *       <li>put the value in the other array
     *       <li>return the other array.
     * </ul>
     * Now imagine the simplicity of getting the values via the new method below:
     * <ul>
     *      <li>Get the array
     *      <li>Call this class with the array, method name
     * </ul>
     *
     * The overhead incurred in the encapsulation of the logic is that for each
     * element in the object [] we are accessing, we call a reflective invoke:
     *
     * which invokes the native
     *
     *
     *
     *
     * @param objs
     * @param accessorName
     * @param declaringClass
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     */
    public static Object[] accessValues(final Object[] objs, String accessorName, 
Class declaringClass)
            throws InvocationTargetException, IllegalAccessException, 
NoSuchMethodException {
        return getInnerValues(objs, makeAccessorMethod(accessorName, declaringClass));
    }

    /**
     * Find the method in the class that returns the property named propname.
     *
     * This is done by checking for an accessor(anycase) for the prop.  get(prop_name)
     * we will be taking the first one.
     *
     * This task is done once per lifetime of the application.
     * @param classObj
     * @param methKey
     * @param propName
     * @return
     */
    private static Method getMethod(final Class classObj,
                                    final Object methKey,
                                    String propName) {
        Object methObj = methods.get(methKey);
        if (methObj != null) return (Method) methObj;
        Method[] methodArr = classObj.getMethods();
        propName = "get"+propName.toLowerCase();
        Method method = null;
        for (int i = 0, len = methodArr.length; i < len; i++)
            if ((method = methodArr[i]).getName().toLowerCase().indexOf(propName) > 
-1) break;

        if (method != null) methods.put(methKey, method);
        return method;
    }

    public static void sort(final Object[] objs, String propName, boolean direction)
            throws InvocationTargetException, IllegalAccessException {
        int size = objs.length;
        if (size < 2) return;
        Class classObj = objs[0].getClass();
        final String methodKey = classObj.getName() + "." +"get"+ 
propName.toLowerCase();
        Method method = getMethod(classObj, methodKey, propName);
        Object[] unsortedValues = getInnerValues(objs, method);
        Object[] sortedValues = new Object[size];

        System.arraycopy(unsortedValues, 0, sortedValues, 0, size);
        Object[] returnObjs = new Object[size];
        Arrays.sort(sortedValues);
        for (int i = 0; i < size; i++) {
            Object val = sortedValues[i];
            for (int j = 0; j < size; j++) {
                if (!val.equals(unsortedValues[j])) continue;
                returnObjs[i] = objs[j];
            }
        }
        if(!direction) {
            System.arraycopy(returnObjs,0,objs,0,size);
            return;
        }
        for (int i = 0, len = objs.length; i < len; i++) objs[i] = returnObjs[--size];
    }

    /**
     *
     * @param objs
     * @param method
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private static Object[] getInnerValues(final Object[] objs, Method method)
            throws InvocationTargetException, IllegalAccessException {
        int size = objs.length;
        Object[] values = new Object[size];
        for (int i = 0; i < size; i++)
            values[i] = method.invoke(objs[i], NO_CLASSES);
        return values;
    }

    /**
     *
     * @param comp
     * @param objs
     * @param accessorName
     * @param declaringClass
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     */
    private static Object[] getSortedInnerValues(Comparator comp,
                                                 final Object[] objs,
                                                 String accessorName,
                                                 Class declaringClass)
            throws InvocationTargetException, IllegalAccessException, 
NoSuchMethodException {
        Object[] values = accessValues(objs, accessorName, declaringClass);
        Arrays.sort(values, comp);
        return values;
    }


    /**
     *
     * @param accessorName
     * @param declaringClass
     * @return
     * @throws NoSuchMethodException
     */
    private static Method makeAccessorMethod(String accessorName, Class declaringClass)
            throws NoSuchMethodException {
        final String methodKey = accessorName + declaringClass.getName();
        Object obj = methods.get(methodKey);
        if (obj != null) return (Method) obj;
        Method method = declaringClass.getMethod(accessorName, NO_CLASSES);
        methods.put(methodKey, method);  //added to system state.
        return method;
    }

    public static String[] asStrings(Object[] objs) {
        int len = objs.length;
        String[] strs = new String[len];
        for (int i = 0; i < len; i++) strs[i] = (String) objs[i];
        return strs;
    }


    /******************   static state **************************/
    private static final Map methods = makeMethodsMap(1);

    private static Map makeMethodsMap(int size) {
        return Collections.synchronizedMap(new HashMap(size, 1f));
    }

    /*******************  test case ******************************/

    /**
     * Test case :)
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        Object[] testStrings = {"All", "Cool", "dudes", "eat", "apple", "pie"};
        int[] neworder = new int[]{0, 2, 3, 1, 4, 5};
        System.out.println(StringUtils.delimit(testStrings, " "));
        ArrayUtils.reorder(testStrings, neworder);
        System.out.println(StringUtils.delimit(testStrings, " "));
        if (true) return;


        Object[] objs = new Object[30];
        for (int i = 0, size = objs.length; i < size; i++) {
            KvPair kvp = new KeyValuePair(new Integer(i), " testing " + 
getRandomNumber(false) + " more test");
            objs[i] = kvp;
        }
        Object[] retObjs = 
ArrayUtils.getSortedInnerValues(StringUtils.STRING_NUMBER_CASE_INSENSITIVE, objs, 
"getValue", KeyValuePair.class);
        for (int i = 0, size = retObjs.length; i < size; i++) {
            System.out.println("getting getValue value" + retObjs[i]);
        }
    }

    private static String getRandomNumber(boolean whole) {
        String number = String.valueOf(Math.random() / 2);
        if (!whole) return number;
        char[] chars = number.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (!Character.isDigit(chars[i])) number = number.substring(i + 1);
        }
        return number;
    }


    static interface KvPair {
        public Object getKey();

        public Object getValue();

        public String toString();
    }

    static class KeyValuePair implements KvPair {
        Object key = null;
        Object value = null;

        public KeyValuePair(Object obj, Object obj1) {
            key = obj;
            value = obj1;
        }

        public Object getKey() {
            return key;
        }

        public Object getValue() {
            return value;
        }

        public String toString() {
            return key + " : " + value;
        }
    }
}
--- NEW FILE: CaseInsensitiveStringAndNumberComparator.java ---
/**
 * Created by IntelliJ IDEA.
 * User: Benjamin Simpson
 * Date: Jan 11, 2003
 * Time: 8:44:51 PM
 */

package com.tablelib.core.lang;

import java.io.Serializable;
import java.util.Comparator;

class CaseInsensitiveStringAndNumberComparator implements Comparator, Serializable {

    /**
    * You might recognise the code as the same java.lang.String.Comparator
    * code for CaseInsensitive
    * @param o1
    * @param o2
    * @return int difference of the two strings
    */
    public int compare(Object o1, Object o2) {
        String s1 = o1.toString();
        String s2 = o2.toString();
        int n1=s1.length(), n2=s2.length();
        for (int i1=0, i2=0; i1<n1 && i2<n2; i1++, i2++) {
            char c1 = s1.charAt(i1);
            char c2 = s2.charAt(i2);
            if (c1 == c2) continue;
            c1 = Character.toUpperCase(c1);
            c2 = Character.toUpperCase(c2);
            if (c1 == c2) continue;
            c1 = Character.toLowerCase(c1);
            c2 = Character.toLowerCase(c2);
            if (c1 == c2) continue;
            return areNumbers(c1,c2) ? compareNumbers(s1,i1,s2,i2) :
                                        c1 -c2;
        }
        return n1 - n2;
    }

    /**
    * Convenience method to check if both characters are "Digits"
    * @param c1
    * @param c2
    * @return boolean are they numbers
    */
    private static boolean areNumbers(char c1, char c2) {
        return Character.isDigit(c1) && Character.isDigit(c2);
    }

    /**
    * Base of the comparators if the string is "like" up until the end where the
    * end is a number.
    *
    * @param s1 Origianal String being compared
    * @param difLoc1 index of the first dissimilar character that is a number in 
string1
    * @param s2 Origianal String being compared to
    * @param difLoc2 index of the first dissimilar character that is a number.
    * @return int value of (s1 - s2) where s1 + s2 are numbers || string comparison if 
it fails due to a nfe.
    */
    private int compareNumbers(final String s1, final int difLoc1,
                              final String s2, final int difLoc2) {
        try {
            return Double.valueOf(getInnerNumber(s1.trim(),difLoc1)).compareTo(
                      Double.valueOf(getInnerNumber(s2.trim(),difLoc2))
                   );
        } catch(NumberFormatException nfe) {
            return s1.compareToIgnoreCase(s2);
        }
    }

    /**
    * Comparators way of finding the entire number
    * This is necessary in the cases of: doubles, different length numbers.
    *
    * @param str The string containing a mix of words and number(s)
    * @param idx
    * @return the untrimed substring containing a number of 0-n length.
    */
    private final String getInnerNumber(final String str, final int idx) {
        final char [] chars = str.toCharArray();
        final int len = chars.length;
        int startOfNumber = idx;
        int endOfNumber = len;

        for(int i = idx; i != 0; i--) {
            char c = chars[i];
            if(Character.isDigit(c) || c == '.') continue;
            startOfNumber = i;
            break;
        }

        for(int i = idx; i < len; i++) {
            if(Character.isDigit(chars[i])) continue;
            endOfNumber = i;
            break;
        }
        return str.substring(startOfNumber,endOfNumber);
    }
}
--- NEW FILE: LongUtils.java ---
package com.javaben.core.lang;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: </p>
 * @author Benjamin Simpson
 * @version 1.0
 */

public class LongUtils {

    public static final Long [] NO_LONGS = new Long[0];
    public static final long [] no_longs = new long[0];

    private LongUtils() {}

    public static long [] primitiveValues(Object [] objs) {
        int size = objs.length;
        long [] longs = new long[size];
        for(int i = 0; i < size; i++) longs[i] = (  (Long) objs[i]  ).longValue();
        return longs;
    }
    public static void main(String[] args) {
    }
}
--- NEW FILE: NumberUtils.java ---
/**
 * Created by IntelliJ IDEA.
 * User: Benjamin Simpson
 * Date: Jan 11, 2003
 * Time: 8:44:51 PM
 */

package com.tablelib.core.lang;

public final class NumberUtils {
    public static final Long [] NO_LONGS = new Long[0];
    public static final long [] no_longs = new long[0];

    /**
     * Test if the object is an int, if so, return it. else return def
     * @param value
     * @param def
     * @return
     */
    public static int parseInt(final Object value, final int def) {
        try {
            return Integer.parseInt(value.toString());
        } catch (java.lang.NumberFormatException nfe) {
            return def;
        }
    }

    public static long [] primitiveValues(Object [] objs) {
        int size = objs.length;
        long [] longs = new long[size];
        for(int i = 0; i < size; i++) longs[i] = (  (Long) objs[i]  ).longValue();
        return longs;
    }
}

--- NEW FILE: StringUtils.java ---
/**
 * Created by IntelliJ IDEA.
 * User: Benjamin Simpson
 * Date: Jan 11, 2003
 * Time: 8:44:51 PM
 */
package com.tablelib.core.lang;

public final class StringUtils {

    public static final CaseInsensitiveStringAndNumberComparator 
STRING_NUMBER_CASE_INSENSITIVE = new CaseInsensitiveStringAndNumberComparator();

    public static String append(final Object[] objs) {
        final StringBuffer buffer = new StringBuffer(objs.length * 10);
        for (int i = 0, len = objs.length; i < len; i++) {
            buffer.append(objs[i].toString());
        }
        return buffer.toString();
    }

    /**
     * Test for null and no length
     * @param val
     * @return
     */
    public static final boolean hasNoValue(final String val) {
        return val == null || val.length() == 0;
    }

    /**
     * Delimit the objects with the delimitor
     * @param strs  if null a "" will be swapped in
     * @param delim
     * @return The appended string
     */
    public static String delimit(final Object[] strs, final String delim) {
        if(hasNoValue(delim)) return append(strs);
        final StringBuffer buff = new StringBuffer();
        for (int i = 0, size = strs.length; i < size; i++) {
            if(i != 0) buff.append(delim);
            if(strs[i] != null) buff.append(strs[i].toString());
        }
        return buff.toString();
    }

    /**
     * Delimit the objects with the delimitor
     * @param strs  if null a "" will be swapped in
     * @param c
     * @return The appended string
     */
    public static String delimit(final Object[] strs, final char c) {
        final StringBuffer buff = new StringBuffer();
        for (int size = strs.length, i = 0; i < size; i++) {
            if (i != 0) buff.append(c);
            if (strs[i] != null) buff.append(strs[i].toString());
        }
        return buff.toString();
    }

    /**
     * Replace character at given index with the same character to upper case
     * This utility was refactored from the StringUtils class in the
     * display taglibs project.  The replaced code is commented out below to see the
     * changes that were made.
     *
     * @param       oldString old string
     * @param       index of replacement
     * @return      String new string
     **/
    public static String toUpperCaseAt(final String oldString,
                                       final int index) {
        final int len = oldString == null ? -1 : oldString.length();
        if(len <= index) return "";
        final char [] chars = oldString.toCharArray();
        chars[index] = Character.toUpperCase(chars[index]);
        return String.valueOf(chars);
    }
    /** former method was pretty bad:
     *
     *
     *  Throwing a null pointer was not necessary
     *
     *  Too many strings were declared or created to change a char
     *  newstring(2x), upper(2x), paddedString, beforeIndex, afterIndex
     *
     public static String toUpperCaseAt( String oldString, int index )
     throws NullPointerException, StringIndexOutOfBoundsException
   {
      int length = oldString.length();
      String newString = "";

      if( index >= length || index < 0 ) {
         throw new StringIndexOutOfBoundsException(
            "Index " + index
            + " is out of bounds for string length " + length );
      }

      //get upper case replacement
      String upper = String.valueOf( oldString.charAt( index ) ).toUpperCase();

      //avoid index out of bounds
      String paddedString = oldString + " ";

      //get reusable parts
      String beforeIndex = paddedString.substring( 0, index );
      String afterIndex = paddedString.substring( index + 1 );

      //generate new String - remove padding spaces
      newString = ( beforeIndex + upper + afterIndex ).substring( 0, length );

      return newString;
   }

     */
}



-------------------------------------------------------
This SF.net email is sponsored by: VM Ware
With VMware you can run multiple operating systems on a single machine.
WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the
same time. Free trial click here: http://www.vmware.com/wl/offer/345/0
_______________________________________________
displaytag-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/displaytag-devel

Reply via email to