View Javadoc
1   package org.andromda.core.common;
2   
3   import java.lang.reflect.Constructor;
4   import java.lang.reflect.Method;
5   import java.util.HashMap;
6   import java.util.Map;
7   import org.apache.log4j.Logger;
8   
9   /**
10   * A class used for converting simple types to other types (i.e.
11   * java.lang.String to java.lang.Integer, etc).
12   *
13   * @author Chad Brandon
14   * @author Bob Fields
15   */
16  public class Converter
17  {
18      /**
19       * The prefix of the 'valueOf' method available on wrapper classes.
20       */
21      private static final String VALUE_OF_METHOD_NAME = "valueOf";
22  
23      /**
24       * The logger instance.
25       */
26      private static final Logger LOGGER = Logger.getLogger(Converter.class);
27  
28      /**
29       * Attempts to convert the <code>object</code> to the <code>expectedType</code>.
30       *
31       * @param object the object to convert.
32       * @param expectedType the type to which it should be converted.
33       * @return the converted object
34       */
35      public static Object convert(
36          Object object,
37          Class expectedType)
38      {
39          Method method = null;
40          try
41          {
42              if (expectedType == String.class)
43              {
44                  object = object.toString();
45              }
46              else if (expectedType == Class.class)
47              {
48                  object = ClassUtils.loadClass(object.toString());
49              }
50              else
51              {
52                  final Class originalType = expectedType;
53                  if (expectedType.isPrimitive())
54                  {
55                      expectedType = (Class)primitiveWrappers.get(expectedType);
56                  }
57                  try
58                  {
59                      method = expectedType.getDeclaredMethod(
60                              VALUE_OF_METHOD_NAME,
61                              new Class[] {object.getClass()});
62                      object = method.invoke(
63                              expectedType,
64                              object);
65                  }
66                  catch (final NoSuchMethodException exception)
67                  {
68                      // - ignore
69                  }
70  
71                  // - if we couldn't find the method try with the constructor
72                  if (method == null)
73                  {
74                      Constructor constructor;
75                      try
76                      {
77                          constructor = expectedType.getConstructor(new Class[] {originalType});
78                          object = constructor.newInstance(object);
79                      }
80                      catch (final NoSuchMethodException exception)
81                      {
82                          throw new IntrospectorException("Could not convert '" + object + "' to type '" +
83                              expectedType.getName() + '\'');
84                      }
85                  }
86              }
87          }
88          catch (Throwable throwable)
89          {
90              if (throwable.getCause()!=null)
91              {
92                  throwable = throwable.getCause();
93              }
94              // At least output the location where the error happened, not the entire stack trace.
95              StackTraceElement[] trace = throwable.getStackTrace();
96              String location = " AT " + trace[0].getClassName() + '.' + trace[0].getMethodName() + ':' + trace[0].getLineNumber();
97              if (throwable.getMessage()!=null)
98              {
99                  location += ' ' + throwable.getMessage();
100             }
101             LOGGER.error("Converter " + throwable + " invoking " + object + " METHOD " + method + " WITH " + expectedType.getName() + location);
102             throw new IntrospectorException(throwable);
103         }
104         return object;
105     }
106 
107     /**
108      * Stores each primitive and its associated wrapper class.
109      */
110     private static final Map primitiveWrappers = new HashMap();
111 
112     /**
113      * Initialize the primitiveWrappers.
114      */
115     static
116     {
117         primitiveWrappers.put(
118             boolean.class,
119             Boolean.class);
120         primitiveWrappers.put(
121             int.class,
122             Integer.class);
123         primitiveWrappers.put(
124             long.class,
125             Long.class);
126         primitiveWrappers.put(
127             short.class,
128             Short.class);
129         primitiveWrappers.put(
130             byte.class,
131             Byte.class);
132         primitiveWrappers.put(
133             float.class,
134             Float.class);
135         primitiveWrappers.put(
136             double.class,
137             Double.class);
138         primitiveWrappers.put(
139             char.class,
140             Character.class);
141     }
142 }