Remove exported everywhere.
[SquirrelJME.git] / modules / tool-classfile / src / main / java / net / multiphasicapps / classfile / Annotation.java
blobcf037d0dc0d10aeccbb8b2302f223e9dd7536602
1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the GNU General Public License v3+, or later.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package net.multiphasicapps.classfile;
12 import cc.squirreljme.runtime.cldc.debug.Debugging;
13 import java.io.DataInputStream;
14 import java.io.IOException;
15 import java.util.LinkedHashMap;
16 import java.util.Map;
17 import net.multiphasicapps.collections.UnmodifiableMap;
19 /**
20 * This represents an annotation which has values assigned to keys.
22 * @since 2018/06/16
24 public final class Annotation
25 implements AnnotationValue
27 /** The type name of the annotation. */
28 protected final ClassName typename;
30 /** The values for the annotation. */
31 private final Map<MethodName, AnnotationValue> _values =
32 new LinkedHashMap<>();
34 /**
35 * Initializes the annotation.
37 * @param __tn The type name to use.
38 * @param __vs The value mappings.
39 * @throws InvalidClassFormatException If an annotation key is duplicated.
40 * @throws NullPointerException On null arguments or if the value mappings
41 * contain a null value.
42 * @since 2018/09/01
44 private Annotation(ClassName __tn, Map<MethodName, AnnotationValue> __vs)
45 throws InvalidClassFormatException, NullPointerException
47 if (__tn == null || __vs == null)
48 throw new NullPointerException("NARG");
50 this.typename = __tn;
52 // Copy key and values over
53 Map<MethodName, AnnotationValue> values = this._values;
54 for (Map.Entry<MethodName, AnnotationValue> e : __vs.entrySet())
56 MethodName k = e.getKey();
57 AnnotationValue v = e.getValue();
59 if (k == null || v == null)
60 throw new NullPointerException();
62 // {@squirreljme.error JC1t Duplicate key within annotation. (The
63 // key)}
64 if (null != values.put(k, v))
65 throw new InvalidClassFormatException(String.format(
66 "JC1t %s", k));
70 /**
71 * {@inheritDoc}
72 * @since 2018/06/16
74 @Override
75 public final boolean equals(Object __o)
77 throw Debugging.todo();
80 /**
81 * Returns the value for the given method name.
83 * @param __n The key to get the value for.
84 * @return The value of the given key.
85 * @throws NullPointerException On null arguments.
86 * @since 2018/06/16
88 public final AnnotationValue get(MethodName __n)
89 throws NullPointerException
91 // Will never be found
92 if (__n == null)
93 throw new NullPointerException("NARG");
95 throw Debugging.todo();
98 /**
99 * {@inheritDoc}
100 * @since 2018/06/16
102 @Override
103 public final int hashCode()
105 throw Debugging.todo();
109 * Returns the key and value map.
111 * @return The key and value map.
112 * @since 2018/10/28
114 public final Map<MethodName, AnnotationValue> keyValueMap()
116 return UnmodifiableMap.<MethodName, AnnotationValue>of(this._values);
120 * {@inheritDoc}
121 * @since 2018/06/16
123 @Override
124 public final String toString()
126 throw Debugging.todo();
130 * Returns the type of this annotation.
132 * @return The annotation type.
133 * @since 2018/06/16
135 public final ClassName type()
137 return this.typename;
141 * Decodes a single annotation from the input data stream and returns the
142 * parsed annotation.
144 * @param __pool The constant pool.
145 * @param __in The input stream to read from.
146 * @return The parsed annotation.
147 * @throws InvalidClassFormatException If the annotation is invalid.
148 * @throws IOException On read errors.
149 * @throws NullPointerException On null arguments.
150 * @since 2018/06/16
152 public static Annotation parse(Pool __pool, DataInputStream __in)
153 throws InvalidClassFormatException, IOException, NullPointerException
155 if (__pool == null || __in == null)
156 throw new NullPointerException("NARG");
158 // Read the type name, which is a class
159 String rawtypename;
160 ClassName typename = new FieldDescriptor((rawtypename = __pool.
161 <UTFConstantEntry>get(UTFConstantEntry.class,
162 __in.readUnsignedShort()).toString())).className();
164 // {@squirreljme.error JC1u Annotation type is not correct. (The type)}
165 if (typename == null)
166 throw new InvalidClassFormatException(String.format("JC1u %s",
167 rawtypename));
169 // Read element table
170 Map<MethodName, AnnotationValue> values = new LinkedHashMap<>();
171 int n = __in.readUnsignedShort();
172 for (int i = 0; i < n; i++)
173 values.put(new MethodName(__pool.<UTFConstantEntry>get(
174 UTFConstantEntry.class, __in.readUnsignedShort()).toString()),
175 Annotation.parseValue(__pool, __in));
177 return new Annotation(typename, values);
181 * Parses a single annotation value.
183 * @param __pool The pool to read from.
184 * @param __in The input stream.
185 * @return The read value.
186 * @throws InvalidClassFormatException If the value is not valid.
187 * @throws IOException On read errors.
188 * @throws NullPointerException On null arguments.
189 * @since 2019/04/01
191 public static AnnotationValue parseValue(Pool __pool,
192 DataInputStream __in)
193 throws InvalidClassFormatException, IOException, NullPointerException
195 if (__pool == null || __in == null)
196 throw new NullPointerException("NARG");
198 // Read tag, which represents the type of things
199 int tag = __in.readUnsignedByte();
200 switch (tag)
202 case 'B':
203 case 'C':
204 case 'I':
205 case 'S':
206 case 'Z':
207 case 'D':
208 case 'F':
209 case 'J':
210 return new AnnotationValuePrimitive(
211 __pool.<ConstantValueNumber>get(ConstantValueNumber.class,
212 __in.readUnsignedShort()).number());
214 case 's':
215 return new AnnotationValueString(
216 __pool.<ConstantValueString>get(ConstantValueString.class,
217 __in.readUnsignedShort()).toString());
219 case 'e':
220 return new AnnotationValueEnum(
221 new FieldDescriptor(__pool.<UTFConstantEntry>get(
222 UTFConstantEntry.class, __in.readUnsignedShort()).
223 toString()),
224 new FieldName(__pool.<UTFConstantEntry>get(
225 UTFConstantEntry.class, __in.readUnsignedShort()).
226 toString()));
228 case 'c':
229 return new AnnotationValueClass(new FieldDescriptor(
230 __pool.<UTFConstantEntry>get(UTFConstantEntry.class,
231 __in.readUnsignedShort()).toString()));
233 case '@':
234 return Annotation.parse(__pool, __in);
236 case '[':
238 // Read length
239 int len = __in.readUnsignedShort();
241 // Read in all values
242 AnnotationValue[] values = new AnnotationValue[len];
243 for (int i = 0; i < len; i++)
244 values[i] = Annotation.parseValue(__pool, __in);
246 // Build
247 return new AnnotationValueArray(values);
250 // {@squirreljme.error JC1v Invalid tag specified in
251 // annotation. (The tag used)}
252 default:
253 throw new InvalidClassFormatException(
254 String.format("JC1v %c", tag));