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-2021 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     /** {@inheritDoc} */
115     @Override
116     public String toString()
117     {
118         return this.value;
119     }
120 
121     /**
122      * @return Returns the parameterDescriptor
123      * @param methodDescriptor String; the methodDescriptor
124      */
125     public static String getParameterDescriptor(final String methodDescriptor)
126     {
127         return methodDescriptor.substring(1, methodDescriptor.indexOf(')'));
128     }
129 
130     /**
131      * returns the parameterTypes.
132      * @param methodDescriptor String; the string
133      * @return ClassDescriptor[] the result
134      * @throws ClassNotFoundException on incomplete classPath
135      */
136     public static Class<?>[] getParameterTypes(final String methodDescriptor) throws ClassNotFoundException
137     {
138         String parameterDescriptor = MethodSignature.getParameterDescriptor(methodDescriptor);
139         List<Class<?>> result = new ArrayList<Class<?>>();
140         int length = 0;
141         while (length < parameterDescriptor.length())
142         {
143             String array = "";
144             while (parameterDescriptor.charAt(length) == '[')
145             {
146                 array = array + "[";
147                 length++;
148             }
149             if (parameterDescriptor.charAt(length) == 'L')
150             {
151                 String argument = parameterDescriptor.substring(length);
152                 argument = array + argument.substring(0, argument.indexOf(';') + 1);
153                 result.add(FieldSignature.toClass(argument));
154                 length = length + argument.length() - array.length();
155             }
156             else
157             {
158                 result.add(FieldSignature.toClass(array + parameterDescriptor.charAt(length)));
159                 length++;
160             }
161         }
162         return result.toArray(new Class<?>[result.size()]);
163     }
164 
165     /**
166      * @return Returns the returnDescriptor
167      * @param methodDescriptor String; the methodDescriptor
168      */
169     public static String getReturnDescriptor(final String methodDescriptor)
170     {
171         return methodDescriptor.substring(methodDescriptor.indexOf(')') + 1);
172     }
173 
174     /**
175      * returns the returnType of this methodDescriptor.
176      * @param methodDescriptor String; the returnDescriptor
177      * @return Returns the returnType
178      * @throws ClassNotFoundException on incomplete classPath
179      */
180     public static Class<?> getReturnType(final String methodDescriptor) throws ClassNotFoundException
181     {
182         return FieldSignature.toClass(MethodSignature.getReturnDescriptor(methodDescriptor));
183     }
184 }