1
2
3
4
5
6
7 package nl.tudelft.simulation.language.reflection;
8
9 import java.io.Serializable;
10 import java.lang.reflect.Array;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import nl.tudelft.simulation.language.primitives.Primitive;
15
16 /***
17 * A field descriptor represents the type of a class, instance, or local
18 * variable. It is a series of characters generated by the grammar described at
19 * <a href =
20 * "http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1169">
21 * The Java Virtual Machine Specification </a>.
22 * <p>
23 * (c) copyright 2002-2005 <a href="http://www.simulation.tudelft.nl">Delft
24 * University of Technology </a>, the Netherlands.
25 * <p>
26 * See for project information <a
27 * href="http://www.simulation.tudelft.nl/dsol/language">www.simulation.tudelft.nl/language
28 * </a> <br>
29 * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
30 * General Public License (LGPL) </a>, no warranty
31 *
32 * @author <a href="http://www.peter-jacobs.com/index.htm">Peter Jacobs </a>, <a
33 * href="mailto:nlang@fbk.eur.nl">Niels Lang </a><a
34 * href="mailto:a.verbraeck@tbm.tudelft.nl">Alexander
35 * Verbraeck </a>
36 * @version $Revision: 1.8 $ $Date: 2005/08/04 12:08:54 $
37 * @since 1.5
38 */
39 public class FieldSignature implements Serializable
40 {
41 /*** the CAHCHE */
42 private static final Map<String, Class> CACHE = new HashMap<String, Class>();
43
44 /*** the value of the field descriptor */
45 private String value;
46
47 /***
48 * constructs a new FieldSignature
49 *
50 * @param value the value of the descriptor
51 */
52 public FieldSignature(final String value)
53 {
54 super();
55 this.value = value;
56 }
57
58 /***
59 * constructs a new FieldSignature
60 *
61 * @param clazz The class
62 */
63 public FieldSignature(final Class clazz)
64 {
65 this(FieldSignature.toDescriptor(clazz));
66 }
67
68 /***
69 * @return Returns the value of the field descriptor
70 */
71 public String getStringValue()
72 {
73 return this.value;
74 }
75
76 /***
77 * @return Returns the value of the field descriptor
78 * @throws ClassNotFoundException if the class cannot be found.
79 */
80 public Class getClassValue() throws ClassNotFoundException
81 {
82 return FieldSignature.toClass(this.value);
83 }
84
85 /***
86 * @see java.lang.Object#toString()
87 */
88 @Override
89 public String toString()
90 {
91 return this.value;
92 }
93
94 /***
95 * converts an array of fields to its descriptor
96 *
97 * @param classes the classes to represent
98 * @return String the descriptor String
99 */
100 public static final String toDescriptor(final Class[] classes)
101 {
102 String result = "";
103 for (int i = 0; i < classes.length; i++)
104 {
105 result = result + FieldSignature.toDescriptor(classes[i]);
106 }
107 return result;
108 }
109
110 /***
111 * converts a field to its descriptor
112 *
113 * @param clazz the clazz to represent
114 * @return String the descriptor String
115 */
116 public static final String toDescriptor(final Class clazz)
117 {
118 if (clazz.getName().startsWith("["))
119 {
120 return clazz.getName().replace('.', '/');
121 }
122 if (clazz.isPrimitive())
123 {
124 if (clazz.equals(int.class))
125 {
126 return "I";
127 }
128 if (clazz.equals(double.class))
129 {
130 return "D";
131 }
132 if (clazz.equals(boolean.class))
133 {
134 return "Z";
135 }
136 if (clazz.equals(char.class))
137 {
138 return "C";
139 }
140 if (clazz.equals(byte.class))
141 {
142 return "B";
143 }
144 if (clazz.equals(float.class))
145 {
146 return "F";
147 }
148 if (clazz.equals(long.class))
149 {
150 return "J";
151 }
152 if (clazz.equals(short.class))
153 {
154 return "S";
155 }
156 return "V";
157 }
158 return "L" + clazz.getName().replace('.', '/') + ";";
159 }
160
161 /***
162 * converts a fieldDescriptor to its class representation
163 *
164 * @param descriptor the descriptor
165 * @return Class the class
166 * @throws ClassNotFoundException on failure
167 */
168 public static final Class toClass(final String descriptor)
169 throws ClassNotFoundException
170 {
171 if (FieldSignature.CACHE.containsKey(descriptor))
172 {
173 return FieldSignature.CACHE.get(descriptor);
174 }
175 String className = descriptor;
176 Class result = null;
177 int array = 0;
178 while (className.charAt(array) == '[')
179 {
180 array++;
181 }
182 className = className.substring(array);
183 if (className.startsWith("L"))
184 {
185 className = className.replaceAll("/", ".");
186 className = className.substring(1, className.length() - 1);
187 try
188 {
189 result = Class.forName(className);
190 } catch (Exception exception)
191 {
192 result = Class.forName(className, true, Thread.currentThread()
193 .getContextClassLoader());
194 }
195 } else
196 {
197 result = Primitive.forName(className);
198 }
199 if (result == null && !descriptor.startsWith("["))
200 {
201
202 return FieldSignature.toClass("L" + descriptor + ";");
203 }
204 if (array == 0)
205 {
206 FieldSignature.CACHE.put(descriptor, result);
207 return result;
208 }
209 try
210 {
211 int[] dimensions = new int[array];
212 result = Array.newInstance(result, dimensions).getClass();
213 } catch (Exception exception)
214 {
215 throw new ClassNotFoundException(result + " class not found");
216 }
217 FieldSignature.CACHE.put(descriptor, result);
218 return result;
219 }
220 }