Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gui4j/core/Gui4jReflectionManager.java


1   package org.gui4j.core;
2   
3   import java.io.Serializable;
4   import java.lang.reflect.InvocationTargetException;
5   import java.lang.reflect.Method;
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import org.apache.commons.logging.Log;
12  import org.apache.commons.logging.LogFactory;
13  import org.gui4j.core.util.MethodCall;
14  import org.gui4j.core.util.MethodCallReflection;
15  import org.gui4j.exception.ErrorTags;
16  import org.gui4j.exception.Gui4jUncheckedException;
17  
18  
19  /**
20   * Supports methods to method declarations by most specific argument types
21   * There is always one instance of this manager in order to cache
22   * method declarations.
23   * 
24   * @author Joachim Schmid
25   */
26  public final class Gui4jReflectionManager implements ErrorTags, Serializable
27  {
28      private static final Log mLogger = LogFactory.getLog(Gui4jReflectionManager.class);
29      private final Map mMethodsClass;
30      private final Map mMethodsName;
31  
32      private Gui4jReflectionManager()
33      {
34          mMethodsClass = new HashMap();
35          mMethodsName = new HashMap();
36      }
37  
38      /**
39       * Returns always the same instance
40       * @return Gui4jReflectionManager
41      */
42      public static Gui4jReflectionManager getNewInstance()
43      {
44          return new Gui4jReflectionManager();
45      }
46  
47      public MethodCall getMethod(
48          String context,
49          Class c,
50          String methodName,
51          Class[] argumentsInit,
52          boolean throwExceptionIfNotFound)
53      {
54          Method[] methods = getMethods(c, methodName);
55          Class[] arguments = new Class[argumentsInit.length];
56          String[] argumentsStr = new String[argumentsInit.length];
57          for (int i = 0; i < argumentsInit.length; i++)
58          {
59              arguments[i] = argumentsInit[i];
60              argumentsStr[i] = argumentsInit[i].getName();
61              /*
62              if (arguments[i].equals(Integer.TYPE))
63              {
64                  arguments[i] = Integer.class;
65              }
66              */
67          }
68  
69          Method lastMethod = null;
70          for (int i = 0; i < methods.length; i++)
71          {
72              if (matching(methods[i], arguments))
73              {
74                  if (lastMethod == null)
75                  {
76                      lastMethod = methods[i];
77                  }
78                  else
79                  {
80                      if (moreSpecific(methods[i], lastMethod))
81                      {
82                          lastMethod = methods[i];
83                      }
84                      else if (moreSpecific(lastMethod, methods[i]))
85                      {
86                          // do nothing
87                      }
88                      else
89                      {
90                          String signature = arr2List(argumentsStr).toString();
91                          signature = signature.replace('[', '(');
92                          signature = signature.replace(']', ')');
93                          Object[] args = { c, methodName, signature };
94                          mLogger.warn("Method ambiguous; context " + context);
95                          mLogger.info("Method 1 = " + lastMethod);
96                          mLogger.info("Method 2 = " + methods[i]);
97                          throw new Gui4jUncheckedException.ProgrammingError(
98                              PROGRAMMING_ERROR_method_ambiguous,
99                              args);
100                     }
101                 }
102             }
103         }
104         if (lastMethod == null && throwExceptionIfNotFound)
105         {
106             String signature = arr2List(argumentsStr).toString();
107             signature = signature.replace('[', '(');
108             signature = signature.replace(']', ')');
109             Object[] args = { c.getName(), methodName, signature, context };
110             mLogger.warn("Method not defined; context " + context);
111             throw new Gui4jUncheckedException.ProgrammingError(PROGRAMMING_ERROR_method_not_found, args);
112         }
113 
114         /*
115         if (methodName.indexOf("getValue")!=-1 && c.getName().indexOf("Ansprache")!=-1)
116         {
117             String signature = arr2List(argumentsStr).toString();
118             signature = signature.replace('[', '(');
119             signature = signature.replace(']', ')');
120         
121             mLogger.debug("Resolve of "+c.getName()+"."+methodName+signature+" = " +lastMethod);
122         }
123         */
124         return MethodCallReflection.getInstance(lastMethod);
125     }
126 
127     /**
128      * Searches for the given class the most specific method. If no
129      * method is found, or if the result is ambiguous, an exception is raised
130      * @param context
131      * @param c
132      * @param methodName
133      * @param argumentsInit
134      * @return MethodCall
135     */
136     public MethodCall getMethod(String context, Class c, String methodName, Class[] argumentsInit)
137     {
138         return getMethod(context, c, methodName, argumentsInit, true);
139     }
140 
141     private List arr2List(Object[] arr)
142     {
143         List l = new ArrayList();
144         for (int i = 0; i < arr.length; i++)
145         {
146             l.add(arr[i]);
147         }
148         return l;
149     }
150 
151     private boolean moreSpecific(Method m1, Method m2)
152     {
153         Class[] parameterTypes1 = m1.getParameterTypes();
154         Class[] parameterTypes2 = m2.getParameterTypes();
155         int n = parameterTypes1.length;
156         for (int i = 0; i < n; i++)
157         {
158             if (!parameterTypes2[i].isAssignableFrom(parameterTypes1[i]))
159             {
160                 return false;
161             }
162         }
163         return true;
164     }
165 
166     private boolean matching(Method m, Class[] arguments)
167     {
168         Class[] parameterTypes = m.getParameterTypes();
169         if (parameterTypes.length != arguments.length)
170         {
171             return false;
172         }
173         for (int i = 0; i < parameterTypes.length; i++)
174         {
175             if (!parameterTypes[i].isAssignableFrom(arguments[i]))
176                 //        !arguments[i].isAssignableFrom(parameterTypes[i]))
177             {
178                 return false;
179             }
180         }
181         return true;
182     }
183 
184     private synchronized Method[] getMethods(Class c, String methodName)
185     {
186         Method[] m = (Method[]) mMethodsName.get(c + "/" + methodName);
187         if (m == null)
188         {
189             Method[] methods = getMethods(c);
190             List methodList = new ArrayList();
191             for (int i = 0; i < methods.length; i++)
192             {
193                 if (methods[i].getName().equals(methodName))
194                 {
195                     methodList.add(methods[i]);
196                 }
197             }
198             m = new Method[methodList.size()];
199             for (int i = 0; i < m.length; i++)
200             {
201                 m[i] = (Method) methodList.get(i);
202             }
203             mMethodsName.put(c + "/" + methodName, m);
204         }
205         return m;
206     }
207 
208     private synchronized Method[] getMethods(Class c)
209     {
210         Method[] methods = (Method[]) mMethodsClass.get(c);
211         if (methods == null)
212         {
213             methods = c.getMethods();
214             /*
215             for (int i = 0; i < methods.length; i++)
216             {
217                 Method m = methods[i];
218                 try
219                 {
220                     methods[i] = c.getMethod(m.getName(),m.getParameterTypes());
221                     System.out.println("Class: "+c.getName()+": "+methods[i]);
222                 }
223                 catch (NoSuchMethodException e)
224                 {
225                     String[] args = { c.getName(), m.getName(), m.toString() };
226                     throw new Gui4jUncheckedException.ProgrammingError(PROGRAMMING_ERROR_method_not_found,args);
227                 }
228             }
229             */
230             mMethodsClass.put(c, methods);
231         }
232         return methods;
233     }
234 
235     /**
236      * Clear the cache in order to use new method declarations
237     */
238     public synchronized void reload()
239     {
240         mMethodsClass.clear();
241         mMethodsName.clear();
242     }
243 
244     public static void handleInvocationTargetException(InvocationTargetException e)
245     {
246         Throwable t = e.getTargetException();
247         if (t != null)
248         {
249             if (t instanceof RuntimeException)
250             {
251                 throw (RuntimeException) t;
252             }
253             if (t instanceof Error)
254             {
255                 throw (Error) t;
256             }
257         }
258     }
259 
260 }