Sun River
          Topics about Java SE, Servlet/JSP, JDBC, MultiThread, UML, Design Pattern, CSS, JavaScript, Maven, JBoss, Tomcat, ...
          posts - 78,comments - 0,trackbacks - 0
          ? In need to save XML representation of your Java object? Here is a simple 200-line class that will do this using reflection. But don't worry, there is some very powerful caching going on, so that the performance will be very good.

          Thanks to comments for pointing out the isAssignableFrom() function in Class. Also, now the resulting XML is valid with all the special characters (&, <, >, &apos; and ").

          package own;
          
          import java.lang.reflect.*;
          import java.util.*;
          
          public class OptimizedReflectionMarshaller {
            // cache for getters
            private static HashMap gettersMap = new HashMap();
          
            // cache for storing info on whether certain class implements Collection
            private static HashMap collectionsMap = new HashMap();
          
            private static final String JAVA = "java.";
            private static final String JAVAX = "javax.";
            
            private static final Class[] EMPTYPARAMS = new Class[0];
            
            /**
             * Info on a single field and the corresponding getter method
             */
            private static class FieldMethodPair {
              private String fieldName;
          
              private Method getterMethod;
          
              public FieldMethodPair(String fieldName, Method getterMethod) {
                this.fieldName = fieldName;
                this.getterMethod = getterMethod;
              }
          
              public String getFieldName() {
                return fieldName;
              }
          
              public Method getGetterMethod() {
                return getterMethod;
              }
            }
          
            /**
             * Returns the marshalled XML representation of the parameter object
             */
            public static String marshal(Object obj) {
              StringBuffer sb = new StringBuffer();
              Class clazz = obj.getClass();
          
              // get class name in lower letters (w/o package name)
              String className = clazz.getName();
              int lastDotIndex = className.lastIndexOf(".");
              if (lastDotIndex >= 0)
                className = className.substring(lastDotIndex + 1);
              className = className.toLowerCase();
          
              sb.append("<" + className + ">");
              marshal(obj, sb);
              sb.append("</" + className + ">");
              return sb.toString();
            }
          
            /**
             * Returns getter function for the specified field
             */
            private static Method getGetter(Class clazz, String fieldName) {
              try {
                // for example, for 'name' we will look for 'getName'
                String getMethodName = fieldName.substring(0, 1);
                getMethodName = getMethodName.toUpperCase();
                getMethodName = "get" + getMethodName
                    + fieldName.substring(1, fieldName.length());
                Method getMethod = clazz.getMethod(getMethodName, EMPTYPARAMS);
                return getMethod;
              } catch (NoSuchMethodException nsme) {
                return null;
              }
            }
          
            /**
             * Returns a list of all fields that have getters
             */
            private static List getAllGetters(Class clazz) {
              try {
                // check if have in cache
                if (gettersMap.containsKey(clazz.getName()))
                  return (List) gettersMap.get(clazz.getName());
          
                List fieldList = new LinkedList();
                Class currClazz = clazz;
                while (true) {
                  Field[] fields = currClazz.getDeclaredFields();
                  for (int i = 0; i < fields.length; i++) {
                    Field currField = fields[i];
                    int modifiers = currField.getModifiers();
                    // check if not static and has getter
                    if (!Modifier.isStatic(modifiers)) {
                      Method getterMethod = getGetter(clazz, currField
                          .getName());
                      if (getterMethod != null) {
                        FieldMethodPair fmp = new FieldMethodPair(currField
                            .getName(), getterMethod);
                        fieldList.add(fmp);
                      }
                    }
                  }
                  currClazz = currClazz.getSuperclass();
                  if (currClazz == null)
                    break;
                }
          
                // store in cache
                gettersMap.put(clazz.getName(), fieldList);
          
                return fieldList;
              } catch (Exception exc) {
                exc.printStackTrace();
                return null;
              }
            }
          
            /**
             * Checks whether the specified class implements Collection interface
             */
            private static boolean isImplementsCollection(Class clazz) {
              String className = clazz.getName();
              // check in cache
              if (collectionsMap.containsKey(className)) {
                return ((Boolean) collectionsMap.get(className)).booleanValue();
              }
          
              boolean result = Collection.class.isAssignableFrom(clazz);
          
              // store in cache
              collectionsMap.put(className, new Boolean(result));
              return result;
            }
          
            private static void appendFormatted(Object obj, StringBuffer sb) {
              String strRepresentation = obj.toString();
              int len = strRepresentation.length();
              for (int i = 0; i < len; i++) {
                char c = strRepresentation.charAt(i);
                switch (c) {
                case '&':
                  sb.append("&amp;");
                  break;
                case '<':
                  sb.append("&lt;");
                  break;
                case '>':
                  sb.append("&gt;");
                  break;
                case '\'':
                  sb.append("&apos;");
                  break;
                case '\"':
                  sb.append("&quot;");
                  break;
                default:
                  sb.append(c);
                }
              }
            }
          
            private static void marshal(Object obj, StringBuffer sb) {
              try {
                Class clazz = obj.getClass();
                String className = clazz.getName();
          
                // check if implements Collection
                if (isImplementsCollection(clazz)) {
                  Collection cobj = (Collection) obj;
                  Iterator it = cobj.iterator();
                  while (it.hasNext()) {
                    Object eobj = it.next();
                    sb.append("<" + eobj.getClass().getName() + ">");
                    marshal(eobj, sb);
                    sb.append("</" + eobj.getClass().getName() + ">");
                  }
                  return;
                }
          
                // check for primitive types
                if (className.startsWith(JAVA) || className.startsWith(JAVAX)) {
                  appendFormatted(obj, sb);
                  return;
                }
          
                // otherwise put all fields with getters
                List allGetters = getAllGetters(clazz);
                Iterator itGetters = allGetters.iterator();
                while (itGetters.hasNext()) {
                  FieldMethodPair currGetter = (FieldMethodPair) itGetters.next();
                  String currFieldName = currGetter.fieldName;
                  Method currentGetter = currGetter.getterMethod;
          
                  // call method
                  Object val = currentGetter.invoke(obj, EMPTYPARAMS);
                  if (val != null) {
                    sb.append("<" + currFieldName + ">");
                    // call recursively
                    marshal(val, sb);
                    sb.append("</" + currFieldName + ">");
                  }
                }
              } catch (Exception e) {
                e.printStackTrace();
              }
            }
          }
          
          
          Feel free to use and modify.
          posted on 2006-09-25 09:36 Sun River 閱讀(661) 評論(0)  編輯  收藏
          主站蜘蛛池模板: 尚志市| 邹平县| 旅游| 资阳市| 沧州市| 南丰县| 东平县| 大渡口区| 略阳县| 金秀| 时尚| 高台县| 泽库县| 郁南县| 济阳县| 普陀区| 娱乐| 商水县| 林西县| 晋宁县| 泰来县| 阳山县| 额济纳旗| 武汉市| 噶尔县| 正宁县| 吕梁市| 大石桥市| 玛纳斯县| 迁西县| 沅陵县| 竹溪县| 德保县| 文昌市| 年辖:市辖区| 河曲县| 广河县| 丹棱县| 哈尔滨市| 南城县| 庆阳市|