Revision: 1461
          http://svn.sourceforge.net/spring-rich-c/?rev=1461&view=rev
Author:   jhoskens
Date:     2006-09-28 04:11:26 -0700 (Thu, 28 Sep 2006)

Log Message:
-----------
refactoring modules: moving ClassUtils

Added Paths:
-----------
    
trunk/spring-richclient/core/src/main/java/org/springframework/richclient/util/ClassUtils.java

Copied: 
trunk/spring-richclient/core/src/main/java/org/springframework/richclient/util/ClassUtils.java
 (from rev 1457, 
trunk/spring-richclient/support/src/main/java/org/springframework/richclient/util/ClassUtils.java)
===================================================================
--- 
trunk/spring-richclient/core/src/main/java/org/springframework/richclient/util/ClassUtils.java
                              (rev 0)
+++ 
trunk/spring-richclient/core/src/main/java/org/springframework/richclient/util/ClassUtils.java
      2006-09-28 11:11:26 UTC (rev 1461)
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2002-2004 the original author or authors.
+ *
+ * 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 org.springframework.richclient.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.URL;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.core.enums.LabeledEnum;
+import org.springframework.core.style.StylerUtils;
+
+/**
+ * Misc static utility functions for java classes.
+ * 
+ * @author Kerth Donald
+ * @author Jim Moore
+ */
+public class ClassUtils {
+       private static final Log logger = LogFactory.getLog(ClassUtils.class);
+
+       private static Set simpleClasses = new HashSet();
+       static {
+               simpleClasses.add(String.class);
+               simpleClasses.add(Integer.class);
+               simpleClasses.add(Float.class);
+               simpleClasses.add(Double.class);
+               simpleClasses.add(Long.class);
+               simpleClasses.add(Short.class);
+               simpleClasses.add(Byte.class);
+               simpleClasses.add(BigInteger.class);
+               simpleClasses.add(Date.class);
+               simpleClasses.add(java.sql.Date.class);
+               simpleClasses.add(Class.class);
+               simpleClasses.add(Boolean.class);
+               simpleClasses.add(Timestamp.class);
+               simpleClasses.add(Calendar.class);
+               simpleClasses.add(URL.class);
+               simpleClasses.add(InetAddress.class);
+       }
+
+       private ClassUtils() {
+       }
+
+       /**
+        * Intializes the specified class if not initialized already.
+        * 
+        * This is required for EnumUtils if the enum class has not yet been 
loaded.
+        */
+       public static void initializeClass(Class clazz) {
+               try {
+                       Class.forName(clazz.getName(), true, 
Thread.currentThread().getContextClassLoader());
+               }
+               catch (ClassNotFoundException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       /**
+        * Returns the qualified class field name with the specified value. For
+        * example, with a class defined with a static field "NORMAL" with 
value =
+        * "0", passing in "0" would return: className.NORMAL.
+        * 
+        * @return The qualified field.
+        */
+       public static String getClassFieldNameWithValue(Class clazz, Object 
value) {
+               Field[] fields = clazz.getFields();
+               for (int i = 0; i < fields.length; i++) {
+                       Field field = fields[i];
+                       try {
+                               Object constant = field.get(null);
+                               if (value.equals(constant)) {
+                                       return clazz.getName() + "." + 
field.getName();
+                               }
+                       }
+                       catch (Exception e) {
+                               e.printStackTrace();
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Gets the field value for the specified qualified field name.
+        */
+       public static Object getFieldValue(String qualifiedFieldName) {
+               Class clazz;
+               try {
+                       clazz = 
classForName(ClassUtils.qualifier(qualifiedFieldName));
+               }
+               catch (ClassNotFoundException cnfe) {
+                       return null;
+               }
+               try {
+                       return 
clazz.getField(ClassUtils.unqualify(qualifiedFieldName)).get(null);
+               }
+               catch (Exception e) {
+                       return null;
+               }
+       }
+
+       /**
+        * Load the class with the specified name.
+        * 
+        * @param name
+        * @return The loaded class.
+        * @throws ClassNotFoundException
+        */
+       public static Class classForName(String name) throws 
ClassNotFoundException {
+               try {
+                       return 
Thread.currentThread().getContextClassLoader().loadClass(name);
+               }
+               catch (Exception e) {
+                       return Class.forName(name);
+               }
+       }
+
+       public static Method findMethod(String methodName, Class clazz, Class[] 
parmTypes) {
+               try {
+                       return clazz.getMethod(methodName, parmTypes);
+               }
+               catch (NoSuchMethodException e) {
+                       return null;
+               }
+       }
+
+       public static String unqualify(String qualifiedName) {
+               return ClassUtils.unqualify(qualifiedName, '.');
+       }
+
+       /**
+        * Returns the unqualified class name of the specified class.
+        * 
+        * @param clazz the class to get the name for
+        * @return The unqualified, short name.
+        */
+       public static String unqualify(Class clazz) {
+               return unqualify(clazz.getName());
+       }
+
+       public static String unqualify(String qualifiedName, char separator) {
+               return 
qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
+       }
+
+       /**
+        * Returns the qualifier for a name separated by dots. The qualified 
part is
+        * everything up to the last dot separator.
+        * 
+        * @param qualifiedName The qualified name.
+        * @return The qualifier portion.
+        */
+       public static String qualifier(String qualifiedName) {
+               int loc = qualifiedName.lastIndexOf('.');
+               if (loc < 0)
+                       return "";
+
+               return qualifiedName.substring(0, loc);
+       }
+
+       /**
+        * Check if the given class represents a primitive array.
+        */
+       public static boolean isPrimitiveArray(Class clazz) {
+               return (clazz.isArray() && 
clazz.getComponentType().isPrimitive());
+       }
+
+       /**
+        * Does the provided bean class represent a simple scalar property? A 
simple
+        * scalar property is considered a value property; that is, it is not
+        * another bean. Examples include primitives, primitive wrappers, 
Enums, and
+        * Strings.
+        */
+       public static boolean isSimpleScalar(Class clazz) {
+               return clazz.isPrimitive() || simpleClasses.contains(clazz) || 
LabeledEnum.class.isAssignableFrom(clazz);
+       }
+
+       public static Method getStaticMethod(String name, Class locatorClass, 
Class[] args) {
+               try {
+                       logger.debug("Attempting to get method '" + name + "' 
on class " + locatorClass + " with arguments '"
+                                       + StylerUtils.style(args) + "'");
+                       Method method = locatorClass.getDeclaredMethod(name, 
args);
+                       if ((method.getModifiers() & Modifier.STATIC) != 0)
+                               return method;
+                       
+                       return null;
+               }
+               catch (NoSuchMethodException e) {
+                       return null;
+               }
+       }
+        
+    private static final Map primativeToWrapperMap = new HashMap();
+    static {
+        primativeToWrapperMap.put(boolean.class, Boolean.class);
+        primativeToWrapperMap.put(char.class, Character.class);
+        primativeToWrapperMap.put(byte.class, Byte.class);
+        primativeToWrapperMap.put(short.class, Short.class);
+        primativeToWrapperMap.put(int.class, Integer.class);
+        primativeToWrapperMap.put(long.class, Long.class);
+        primativeToWrapperMap.put(float.class, Float.class);
+        primativeToWrapperMap.put(double.class, Double.class);
+    }
+
+    public static Class convertPrimitiveToWrapper(Class clazz) {
+        if (!clazz.isPrimitive())
+            return clazz;
+
+        return (Class)primativeToWrapperMap.get(clazz);
+    }
+
+       /**
+        * Given a [EMAIL PROTECTED] Map}where the keys are [EMAIL PROTECTED] 
Class}es, search the map
+        * for the closest match of the key to the <tt>typeClass</tt>. This is
+        * extremely useful to support polymorphism (and an absolute 
requirement to
+        * find proxied classes where classes are acting as keys in a map).
+        * <p />
+        * 
+        * For example: If the Map has keys of Number.class and String.class, 
using
+        * a <tt>typeClass</tt> of Long.class will find the Number.class entry 
and
+        * return its value.
+        * <p />
+        * 
+        * When doing the search, it looks for the most exact match it can, 
giving
+        * preference to interfaces over class inheritance. As a performance
+        * optimiziation, if it finds a match it stores the derived match in 
the map
+        * so it does not have to be derived again.
+        * 
+        * @param typeClass the kind of class to search for
+        * @param classMap the map where the keys are of type Class
+        * @return null only if it can't find any match
+        */
+       public static Object getValueFromMapForClass(final Class typeClass, 
final Map classMap) {
+               Object val = classMap.get(typeClass);
+               if (val == null) {
+                       // search through the interfaces first
+                       val = getValueFromMapForInterfaces(typeClass, classMap);
+
+                       if (val == null) {
+                               // now go up through the inheritance hierarchy
+                               val = getValueFromMapForSuperClass(typeClass, 
classMap);
+                       }
+
+                       if (val == null) {
+                               // not found anywhere
+                               if (logger.isDebugEnabled()) {
+                                       logger.debug("Could not find a 
definition for " + typeClass + " in " + classMap.keySet());
+                               }
+                               return null;
+                       }
+
+            // remember this so it doesn't have to be looked-up again
+                       classMap.put(typeClass, val);
+                       return val;
+               }
+               return val;
+       }
+
+       private static Object getValueFromMapForInterfaces(final Class 
typeClass, final Map classMap) {
+               final Class[] interfaces = typeClass.getInterfaces();
+
+               if (logger.isDebugEnabled()) {
+                       logger.debug("searching through " + 
Arrays.asList(interfaces));
+               }
+
+               for (int i = 0; i < interfaces.length; i++) {
+                       final Class anInterface = interfaces[i];
+                       final Object val = classMap.get(anInterface);
+                       if (val != null) {
+                               return val;
+                       }
+               }
+
+               // not found, but now check the parent interfaces
+               for (int i = 0; i < interfaces.length; i++) {
+                       final Class anInterface = interfaces[i];
+                       final Object val = 
getValueFromMapForInterfaces(anInterface, classMap);
+                       if (val != null) {
+                               return val;
+                       }
+               }
+
+               return null;
+       }
+
+       private static Object getValueFromMapForSuperClass(final Class 
typeClass, final Map classMap) {
+               Class superClass = typeClass.getSuperclass();
+               while (superClass != null) {
+                       if (logger.isDebugEnabled()) {
+                               logger.debug("searching for " + superClass);
+                       }
+                       Object val = classMap.get(superClass);
+                       if (val != null) {
+                               return val;
+                       }
+
+                       // try the interfaces
+                       val = getValueFromMapForInterfaces(superClass, 
classMap);
+                       if (val != null) {
+                               return val;
+                       }
+
+                       superClass = superClass.getSuperclass();
+               }
+               return null;
+       }
+
+       /**
+        * Is the given name a property in the class? In other words, does it 
have a
+        * setter and/or a getter method?
+        * 
+        * @param theClass the class to look for the property in
+        * @param propertyName the name of the property
+        * 
+        * @return true if there is either a setter or a getter for the property
+        * 
+        * @throws IllegalArgumentException if either argument is null
+        */
+       public static boolean isAProperty(Class theClass, String propertyName) {
+               if (theClass == null)
+                       throw new IllegalArgumentException("theClass == null");
+               if (propertyName == null)
+                       throw new IllegalArgumentException("propertyName == 
null");
+
+               if (getReadMethod(theClass, propertyName) != null)
+                       return true;
+               if (getWriteMethod(theClass, propertyName) != null)
+                       return true;
+               return false;
+       }
+
+       private static Method getReadMethod(Class theClass, String 
propertyName) {
+               // handle "embedded/dotted" properties
+               if (propertyName.indexOf('.') > -1) {
+                       final int index = propertyName.indexOf('.');
+                       final String firstPropertyName = 
propertyName.substring(0, index);
+                       final String restOfPropertyName = 
propertyName.substring(index + 1, propertyName.length());
+                       final Class firstPropertyClass = 
getPropertyClass(theClass, firstPropertyName);
+                       return getReadMethod(firstPropertyClass, 
restOfPropertyName);
+               }
+
+               final String getterName = "get" + propertyName.substring(0, 
1).toUpperCase()
+                               + (propertyName.length() == 1 ? "" : 
propertyName.substring(1));
+
+               Method method = getMethod(theClass, getterName);
+               if (method == null) {
+                       final String isserName = "is" + 
propertyName.substring(0, 1).toUpperCase()
+                                       + (propertyName.length() == 1 ? "" : 
propertyName.substring(1));
+                       method = getMethod(theClass, isserName);
+               }
+
+               if (method == null) {
+                       logger.info("There is not a getter for " + propertyName 
+ " in " + theClass);
+                       return null;
+               }
+
+               if (!Modifier.isPublic(method.getModifiers())) {
+                       logger.warn("The getter for " + propertyName + " in " + 
theClass + " is not public: " + method);
+                       return null;
+               }
+
+               if (Void.TYPE.equals(method.getReturnType())) {
+                       logger.warn("The getter for " + propertyName + " in " + 
theClass + " returns void: " + method);
+                       return null;
+               }
+
+               if (method.getName().startsWith("is")
+                               && 
!(Boolean.class.equals(method.getReturnType()) || 
Boolean.TYPE.equals(method.getReturnType()))) {
+                       logger.warn("The getter for " + propertyName + " in " + 
theClass
+                                       + " uses the boolean naming convention 
but is not boolean: " + method);
+                       return null;
+               }
+
+               return method;
+       }
+
+       private static Method getMethod(final Class theClass, final String 
getterName) {
+               try {
+                       return theClass.getMethod(getterName, null);
+               }
+               catch (NoSuchMethodException e) {
+                       return null;
+               }
+       }
+
+       private static Method getWriteMethod(Class theClass, String 
propertyName) {
+               // handle "embedded/dotted" properties
+               if (propertyName.indexOf('.') > -1) {
+                       final int index = propertyName.indexOf('.');
+                       final String firstPropertyName = 
propertyName.substring(0, index);
+                       final String restOfPropertyName = 
propertyName.substring(index + 1, propertyName.length());
+                       final Class firstPropertyClass = 
getPropertyClass(theClass, firstPropertyName);
+                       return getWriteMethod(firstPropertyClass, 
restOfPropertyName);
+               }
+
+               final String setterName = "set" + propertyName.substring(0, 
1).toUpperCase()
+                               + (propertyName.length() == 1 ? "" : 
propertyName.substring(1));
+
+               final Method[] methods = theClass.getMethods();
+               for (int i = 0; i < methods.length; i++) {
+                       Method method = methods[i];
+                       if (setterName.equals(method.getName()) && 
method.getParameterTypes().length == 1) {
+
+                               if (!Modifier.isPublic(method.getModifiers())) {
+                                       logger.warn("The setter for " + 
propertyName + " in " + theClass + " is not public: " + method);
+                                       return null;
+                               }
+
+                               if (!Void.TYPE.equals(method.getReturnType())) {
+                                       logger.warn("The setter for " + 
propertyName + " in " + theClass + " is not void: " + method);
+                                       return null;
+                               }
+
+                               return method;
+                       }
+               }
+
+               logger.info("There is not a setter for " + propertyName + " in 
" + theClass);
+               return null;
+       }
+
+       /**
+        * Returns the class of the property.
+        * <p />
+        * 
+        * For example, getPropertyClass(JFrame.class, "size") would return the
+        * java.awt.Dimension class.
+        * 
+        * @param parentClass the class to look for the property in
+        * @param propertyName the name of the property
+        * 
+        * @return the class of the property; never null
+        * 
+        * @throws IllegalArgumentException if either argument is null
+        * @throws IllegalArgumentException <tt>propertyName</tt> is not a
+        *         property of <tt>parentClass</tt>
+        */
+       public static Class getPropertyClass(Class parentClass, String 
propertyName) throws IllegalArgumentException {
+               if (parentClass == null)
+                       throw new IllegalArgumentException("theClass == null");
+               if (propertyName == null)
+                       throw new IllegalArgumentException("propertyName == 
null");
+
+               final Method getterMethod = getReadMethod(parentClass, 
propertyName);
+               if (getterMethod != null) {
+                       return getterMethod.getReturnType();
+               }
+
+               final Method setterMethod = getWriteMethod(parentClass, 
propertyName);
+               if (setterMethod != null) {
+                       return setterMethod.getParameterTypes()[0];
+               }
+
+               throw new IllegalArgumentException(propertyName + " is not a 
property of " + parentClass);
+       }
+
+}
\ No newline at end of file


Property changes on: 
trunk/spring-richclient/core/src/main/java/org/springframework/richclient/util/ClassUtils.java
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
spring-rich-c-cvs mailing list
spring-rich-c-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs

Reply via email to