View Javadoc
1   package org.djutils.reflection;
2   
3   import java.lang.reflect.Constructor;
4   import java.lang.reflect.Method;
5   import java.util.ArrayList;
6   import java.util.List;
7   
8   /**
9    * A method descriptor represents the parameters that the method takes and the value that it returns. It is a series of
10   * characters generated by the grammar described at
11   * <a href = "https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3"> The Java Virtual Machine
12   * Specification: Method Descriptors </a>.
13   * <p>
14   * Copyright (c) 2002-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
15   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
16   * distributed under a three-clause BSD-style license, which can be found at
17   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
18   * </p>
19   * @author Peter Jacobs, Niels Lang, Alexander Verbraeck
20   */
21  public class MethodSignature
22  {
23      /** the value of the methodDescriptor. */
24      private String value = null;
25  
26      /**
27       * constructs a new MethodSignature.
28       * @param value the descriptor
29       */
30      public MethodSignature(final String value)
31      {
32          this.value = value;
33      }
34  
35      /**
36       * constructs a new MethodSignature.
37       * @param method the method
38       */
39      public MethodSignature(final Method method)
40      {
41          Class<?>[] parameterTypes = new Class<?>[0];
42          if (method.getParameterTypes() != null)
43          {
44              parameterTypes = method.getParameterTypes();
45          }
46          this.value = "(";
47          for (int i = 0; i < parameterTypes.length; i++)
48          {
49              this.value = this.value + FieldSignature.toDescriptor(parameterTypes[i]);
50          }
51          this.value = this.value + ")" + FieldSignature.toDescriptor(method.getReturnType());
52      }
53  
54      /**
55       * constructs a new MethodSignature.
56       * @param constructor the constructor
57       */
58      public MethodSignature(final Constructor<?> constructor)
59      {
60          Class<?>[] parameterTypes = new Class<?>[0];
61          if (constructor.getParameterTypes() != null)
62          {
63              parameterTypes = constructor.getParameterTypes();
64          }
65  
66          this.value = "(";
67          for (int i = 0; i < parameterTypes.length; i++)
68          {
69              this.value = this.value + FieldSignature.toDescriptor(parameterTypes[i]);
70          }
71          this.value = this.value + ")" + FieldSignature.toDescriptor(constructor.getDeclaringClass());
72      }
73  
74      /**
75       * @return Returns the parameterDescriptor
76       */
77      public String getParameterDescriptor()
78      {
79          return MethodSignature.getParameterDescriptor(this.value);
80      }
81  
82      /**
83       * returns the parameterTypes.
84       * @return ClassDescriptor[] the result
85       * @throws ClassNotFoundException on incomplete classPath
86       */
87      public Class<?>[] getParameterTypes() throws ClassNotFoundException
88      {
89          return MethodSignature.getParameterTypes(this.value);
90      }
91  
92      /**
93       * @return Returns the returnDescriptor.
94       */
95      public String getReturnDescriptor()
96      {
97          return MethodSignature.getReturnDescriptor(this.value);
98      }
99  
100     /**
101      * returns the returnType of this methodDescriptor.
102      * @return Returns the returnType
103      * @throws ClassNotFoundException on incomplete classPath
104      */
105     public Class<?> getReturnType() throws ClassNotFoundException
106     {
107         return MethodSignature.getReturnType(this.value);
108     }
109 
110     @Override
111     public String toString()
112     {
113         return this.value;
114     }
115 
116     /**
117      * @return Returns the parameterDescriptor
118      * @param methodDescriptor the methodDescriptor
119      */
120     public static String getParameterDescriptor(final String methodDescriptor)
121     {
122         return methodDescriptor.substring(1, methodDescriptor.indexOf(')'));
123     }
124 
125     /**
126      * returns the parameterTypes.
127      * @param methodDescriptor the string
128      * @return ClassDescriptor[] the result
129      * @throws ClassNotFoundException on incomplete classPath
130      */
131     public static Class<?>[] getParameterTypes(final String methodDescriptor) throws ClassNotFoundException
132     {
133         String parameterDescriptor = MethodSignature.getParameterDescriptor(methodDescriptor);
134         List<Class<?>> result = new ArrayList<Class<?>>();
135         int length = 0;
136         while (length < parameterDescriptor.length())
137         {
138             String array = "";
139             while (parameterDescriptor.charAt(length) == '[')
140             {
141                 array = array + "[";
142                 length++;
143             }
144             if (parameterDescriptor.charAt(length) == 'L')
145             {
146                 String argument = parameterDescriptor.substring(length);
147                 argument = array + argument.substring(0, argument.indexOf(';') + 1);
148                 result.add(FieldSignature.toClass(argument));
149                 length = length + argument.length() - array.length();
150             }
151             else
152             {
153                 result.add(FieldSignature.toClass(array + parameterDescriptor.charAt(length)));
154                 length++;
155             }
156         }
157         return result.toArray(new Class<?>[result.size()]);
158     }
159 
160     /**
161      * @return Returns the returnDescriptor
162      * @param methodDescriptor the methodDescriptor
163      */
164     public static String getReturnDescriptor(final String methodDescriptor)
165     {
166         return methodDescriptor.substring(methodDescriptor.indexOf(')') + 1);
167     }
168 
169     /**
170      * returns the returnType of this methodDescriptor.
171      * @param methodDescriptor the returnDescriptor
172      * @return Returns the returnType
173      * @throws ClassNotFoundException on incomplete classPath
174      */
175     public static Class<?> getReturnType(final String methodDescriptor) throws ClassNotFoundException
176     {
177         return FieldSignature.toClass(MethodSignature.getReturnDescriptor(methodDescriptor));
178     }
179 }