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