MiscTools.java :  » Messenger » joscar » net » kano » joscar » Java Open Source

Java Open Source » Messenger » joscar 
joscar » net » kano » joscar » MiscTools.java
/*
 *  Copyright (c) 2002-2003, The Joust Project
 *  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 the Joust Project 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 THE 
 *  COPYRIGHT OWNER OR CONTRIBUTORS 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.
 *
 *  File created by keith @ Mar 28, 2003
 *
 */

package net.kano.joscar;

import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Pattern;

/**
 * Provides a set of miscellaneous tools used throughout joscar.
 */
public final class MiscTools {
    /**
     * This private constructor is never called, ensuring that an instance of
     * <code>MiscTools</code> will not be created.
     */
    private MiscTools() { }

    /**
     * Returns the class name of the given object, with the package name
     * stripped off. There must be a better way to do this.
     *
     * @param obj the object whose class name will be returned
     * @return the class name of the given object, without package name
     */
    public static String getClassName(Object obj) {
        return getClassName(obj.getClass());
    }

    /**
     * Returns the name of the given class, with the package name stripped off.
     *
     * @param cl the class whose name will be returned
     * @return the name of the given class, without package name
     */
    public static String getClassName(Class<?> cl) {
        return getClassName(cl.getName());
    }

    /**
     * Returns the class name of the given fully qualified class name. For
     * example, <code>getClassName("net.kano.joscar.MiscTools")</code> would
     * produce the string <code>"MiscTools"</code>.
     *
     * @param fullName the fully qualified class name
     * @return the given fully qualified class name, without the package name
     */
    public static String getClassName(String fullName) {
        return fullName.substring(fullName.lastIndexOf('.') + 1);
    }

    /**
     * Finds a <code>static final</code> field of the given class whose name
     * matches the given pattern and whose value is equal to the given
     * <code>value</code>. The field's name is returned, or <code>null</code> if
     * no field is found.
     *
     * @param cl a class
     * @param value the value to search for
     * @param pattern a regular expression pattern that matches the fields to be
     *        searched, or <code>null</code> to match all fields of the class
     * @return the name of a field matching the given constraints
     */
    public static @Nullable String findIntField(Class<?> cl, long value,
            String pattern) {
        Pattern p = pattern == null ? null : Pattern.compile(pattern);

        for (Field field : cl.getFields()) {
            int modifiers = field.getModifiers();

            // only accept static final fields
            if (!Modifier.isStatic(modifiers) || !Modifier.isFinal(modifiers)) {
                continue;
            }

            String fieldName = field.getName();
            if (p != null && !p.matcher(fieldName).matches()) continue;

            try {
                if (field.getLong(null) == value) return fieldName;
            } catch (IllegalAccessException e) {
                continue;
            }
        }

        // we couldn't find anything
        return null;
    }

    /**
     * Finds a <code>static final</code> field of the given class whose name
     * matches the given pattern and whose value is equal to the given
     * <code>value</code>. The field's name is returned, or <code>null</code> if
     * no field is found.
     *
     * @param cl a class
     * @param value the value to search for
     * @param pattern a regular expression pattern that matches the fields to be
     *        searched, or <code>null</code> to match all fields of the class
     * @return the name of a field matching the given constraints
     */
    public static @Nullable String findEqualField(Class<?> cl, Object value,
            String pattern) {
        Pattern p = pattern == null ? null : Pattern.compile(pattern);

        for (Field field : cl.getFields()) {
            int modifiers = field.getModifiers();
            if (!Modifier.isStatic(modifiers) || !Modifier.isFinal(modifiers)) {
                continue;
            }

            String fieldName = field.getName();
            if (p != null && !p.matcher(fieldName).matches()) continue;

            Object fieldValue;
            try {
                fieldValue = field.get(null);
            } catch (IllegalAccessException e) {
                continue;
            }
            if (fieldValue == null) {
                if (value == null) return fieldName;
            } else {
                // fieldValue is not null
                if (fieldValue.equals(value)) return fieldName;
            }
        }

        // we didn't find anything
        return null;
    }

    /**
     * Returns a list of names of public static final fields in the given class
     * whose values' "on" bits are a subset of the "on" bits in the given
     * value's binary representation, and whose name matches the given regular
     * expression pattern.
     * <p>
     * For example, given the class:
     * <pre>
class Something {
     private static final int FLAG_A = 0x04;
     private static final int FLAG_B = 0x02;
     private static final int FLAG_C = 0x08;
}
</pre>
     * The call <code>MiscTools.findFlagFields(Something.class, 0x02 | 0x08 |
     * 0x01 | 0x40, Pattern.compile("FLAG_.*"))</code> would return an array
     * containing <code>"FLAG_B"</code> and <code>"FLAG_C"</code>.
     *
     * @param cl the class containing the fields
     * @param value the value to match
     * @param p the regular expression pattern that matching fields must match
     * @return an array of field names matching the given criteria
     *
     * @see #getFlagFieldsString(Class, long, String)
     */
    public static Collection<String> findFlagFields(Class<?> cl, long value,
            String p) {
        Field[] fields = cl.getFields();
        SortedMap<Long,String> matches = new TreeMap<Long, String>(Collections.reverseOrder());
        Pattern pattern = p == null ? null : Pattern.compile(p);

        for (Field field : fields) {
            int modifiers = field.getModifiers();

            // only accept static final fields
            if (!Modifier.isStatic(modifiers) || !Modifier.isFinal(modifiers)) {
                continue;
            }

            String fieldName = field.getName();
            if (pattern != null && !pattern.matcher(fieldName).matches()) {
                continue;
            }

            long fieldValue;
            try {
                fieldValue = field.getLong(null);
            } catch (IllegalAccessException e) {
                continue;
            }

            if ((value & fieldValue) == fieldValue) {
                matches.put(fieldValue, fieldName);
            }
        }

        Collection<String> values = matches.values();
        return Collections.unmodifiableCollection(values);
    }

    /**
     *
     * Returns a textual list of names of public static final fields in the
     * given class whose values' "on" bits are a subset of the "on" bits in the
     * given value's binary representation, and whose name matches the given
     * regular expression pattern. If any bits in the given value are not set in
     * any of the matching fields, a number whose binary representation contains
     * the remaining bits will be appended to the end of the string.
     * <p>
     * For example, given the class:
     * <pre>
class Something {
    private static final int FLAG_A = 0x04;
    private static final int FLAG_B = 0x02;
    private static final int FLAG_C = 0x08;
}
     </pre>
     * The call <code>MiscTools.findFlagFields(Something.class, 0x02 | 0x08 |
     * 0x01 | 0x40, Pattern.compile("FLAG_.*"))</code> would return
     * <code>"FLAG_B | FLAG_C | 0x41"</code>.
     *
     * @param cl the class containing the fields
     * @param value the value to match
     * @param pattern the regular expression pattern that matching fields must
     *        match
     * @return a string containing the names of the matching fields
     */
    public static String getFlagFieldsString(Class<?> cl, long value,
            String pattern) {
        Collection<String> fields = findFlagFields(cl, value, pattern);

        StringBuffer b = new StringBuffer();
        long covered = 0;
        boolean first = true;
        for (String field : fields) {
            long fieldValue = 0;
            try {
                fieldValue = cl.getField(field).getLong(null);
            } catch (NoSuchFieldException ignored) {
            } catch (SecurityException ignoredToo) {
            } catch (IllegalAccessException ignoredThree) {
            }
            if ((covered | fieldValue) == covered) continue;

            covered |= fieldValue;

            if (first) {
                first = false;
            } else {
                b.append(" | ");
            }
            b.append(field);
        }

        if (covered != 0 && (value & ~covered) != 0) {
            b.append(" | 0x");
            b.append(Long.toHexString(value & ~covered));
        }

        return b.toString();
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.