110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipackage annotations; 210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 399159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl/*>>> 443367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport org.checkerframework.checker.nullness.qual.Nullable; 599159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl*/ 610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernstimport annotations.el.AnnotationDef; 802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernstimport annotations.field.AnnotationFieldType; 902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst 1010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Aliimport java.util.*; 1102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernstimport java.lang.reflect.*; 1202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst 1310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali/** 1510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * A very simple annotation representation constructed with a map of field names 1610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * to values. See the rules for values on {@link Annotation#getFieldValue}; 1710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * furthermore, subannotations must be {@link Annotation}s. 1810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link Annotation}s are immutable. 1910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * 2010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <p> 2110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link Annotation}s can be constructed directly or through 2210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link AnnotationFactory#saf}. Either way works, but if you construct 2310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * one directly, you must provide a matching {@link AnnotationDef} yourself. 2410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 253aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernstpublic final class Annotation { 2610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 2710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 2810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * The annotation definition. 2910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 3010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public final AnnotationDef def; 3110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 3210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 3310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * An unmodifiable copy of the passed map of field values. 3410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 353aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public final Map<String, Object> fieldValues; 3610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 3702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst /** Check the representation, throw assertion failure if it is violated. */ 3802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst public void checkRep() { 3963adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst assert fieldValues != null; 4063adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst assert fieldValues.keySet() != null; 4163adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst assert def != null; 4263adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst assert def.fieldTypes != null; 4363adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst assert def.fieldTypes.keySet() != null; 4402ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst if (! fieldValues.keySet().equals(def.fieldTypes.keySet())) { 4502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst for (String s : fieldValues.keySet()) { 4602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst assert def.fieldTypes.containsKey(s) 4702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst : String.format("Annotation contains field %s but AnnotationDef does not%n annotation: %s%n def: %s%n", s, this, this.def); 4802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 49d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali // TODO: Faulty assertions, fails when default value is used 50d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali// for (String s : def.fieldTypes.keySet()) { 51d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali// assert fieldValues.containsKey(s) 52d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali// : String.format("AnnotationDef contains field %s but Annotation does not", s); 53d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali// } 54d3512bff0c69914f91f751a1f36f3da6449f93d9Mahmood Ali// assert false : "This can't happen."; 5502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 5602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst 5702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst for (String fieldname : fieldValues.keySet()) { 5802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst AnnotationFieldType aft = def.fieldTypes.get(fieldname); 5902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst Object value = fieldValues.get(fieldname); 6002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst String valueString; 6163adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst String classString = value.getClass().toString(); 6202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst if (value instanceof Object[]) { 6363adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst Object[] arr = (Object[]) value; 6463adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst valueString = Arrays.toString(arr); 6563adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += " {"; 6663adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst for (Object elt : arr) { 6763adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += " " + elt.getClass(); 6863adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst } 6963adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += "}"; 7063adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst } else if (value instanceof Collection) { 71a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl Collection<?> coll = (Collection<?>) value; 7263adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst valueString = Arrays.toString(coll.toArray()); 7363adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += " {"; 7463adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst for (Object elt : coll) { 7563adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += " " + elt.getClass(); 7663adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst } 7763adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst classString += " }"; 7802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } else { 7902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst valueString = value.toString(); 8063adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst // No need to modify valueString. 8102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 8202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst assert aft.isValidValue(value) 8363adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst : String.format("Bad field value%n %s (%s)%nfor field%n %s (%s)%nin annotation%n %s", 8463adeb8daeeb8c986ffe3d4e7fa5d93109616fbeMichael Ernst valueString, classString, aft, aft.getClass(), def); 8502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 8602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 8702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst 8810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // TODO make sure the field values are valid? 8910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 9010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Constructs a {@link Annotation} with the given definition and 9110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * field values. Make sure that the field values obey the rules given on 9210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link Annotation#getFieldValue} and that subannotations are also 9310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link Annotation}s; this constructor does not validate the 9410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * values. 9510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 9610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public Annotation(AnnotationDef def, 973aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst Map<String, ? extends Object> fields) { 9810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali this.def = def; 9910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali this.fieldValues = Collections.unmodifiableMap( 1003aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst new LinkedHashMap<String, Object>(fields)); 10102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst checkRep(); 10202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 10302ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst 10402ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst /** Use adefs to look up (or insert into it) missing AnnotationDefs. */ 10502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst public Annotation(java.lang.annotation.Annotation ja, Map<String, AnnotationDef> adefs) { 10602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst Class<? extends java.lang.annotation.Annotation> jaType = ja.annotationType(); 10702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst String name = jaType.getName(); 10802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst if (adefs.containsKey(name)) { 10902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst def = adefs.get(name); 11002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } else { 11102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst def = AnnotationDef.fromClass(jaType, adefs); 11202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst adefs.put(name, def); 11302ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 11402ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst fieldValues = new LinkedHashMap<String,Object>(); 11502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst try { 11602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst for (String fieldname : def.fieldTypes.keySet()) { 11702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst AnnotationFieldType aft = def.fieldTypes.get(fieldname); 11802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst Method m = jaType.getDeclaredMethod(fieldname); 11902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst Object val = m.invoke(ja); 12002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst if (! aft.isValidValue(val)) { 12199159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl if (val instanceof Class[]) { 122a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl Class<?>[] vala = (Class[]) val; 123a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl List<Class<?>> vall = new ArrayList<Class<?>>(vala.length); 124a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl for (Class<?> elt : vala) { 12599159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl vall.add(elt); 12699159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl } 12799159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl val = vall; 12899159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl } else if (val instanceof Object[]) { 12902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst Object[] vala = (Object[]) val; 13002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst List<Object> vall = new ArrayList<Object>(vala.length); 13102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst for (Object elt : vala) { 13202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst vall.add(elt.toString()); 13302ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 13402ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst val = vall; 13502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } else { 13602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst val = val.toString(); 13702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 13802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 13902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst assert aft.isValidValue(val) 14099159a24fbaf231aacf98ae0a47fcdd9d7abf5f3wdietl : String.format("invalid value \"%s\" for field \"%s\" of class \"%s\" and expected type \"%s\"; ja=%s", val, val.getClass(), fieldname, aft, ja); 14102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst fieldValues.put(fieldname, val); 14202ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 14302ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } catch (NoSuchMethodException e) { 14402ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst throw new Error(String.format("no such method (annotation field) in %s%n from: %s %s", jaType, ja, adefs), e); 14502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } catch (InvocationTargetException e) { 14602ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst throw new Error(e); 14702ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } catch (IllegalAccessException e) { 14802ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst throw new Error(e); 14902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst } 15002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst checkRep(); 15110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 15210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 15310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 15410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Returns the value of the field whose name is given. 15510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * 15610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <p> 15710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Everywhere in the annotation scene library, field values are to be 15810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * represented as follows: 15910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * 16010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <ul> 16110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Primitive value: wrapper object, such as {@link Integer}. 16210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>{@link String}: {@link String}. 16310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Class token: name of the type as a {@link String}, using the source 16410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * code notation <code>int[]</code> for arrays. 16510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Enumeration constant: name of the constant as a {@link String}. 16610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Subannotation: <code>Annotation</code> object. 16710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <li>Array: {@link List} of elements in the formats defined here. If 16810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * the element type is unknown (see 16910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link AnnotationBuilder#addEmptyArrayField}), the array must have zero 17010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * elements. 17110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * </ul> 17210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 1733aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public Object getFieldValue(String fieldName) { 17410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return fieldValues.get(fieldName); 17510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 17610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 17710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 17810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Returns the definition of the annotation type to which this annotation 17910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * belongs. 18010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 18110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public final AnnotationDef def() { 18210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return def; 18310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 18410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 18510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 18610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * This {@link Annotation} equals <code>o</code> if and only if 18710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <code>o</code> is a nonnull {@link Annotation} and <code>this</code> and 18810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * <code>o</code> have recursively equal definitions and field values, 18910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * even if they were created by different {@link AnnotationFactory}s. 19010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 19110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 1923aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public final boolean equals(Object o) { 19310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return o instanceof Annotation && equals((Annotation) o); 19410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 19510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 19610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 19710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Returns whether this annotation equals <code>o</code>; a slightly faster 19810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * variant of {@link #equals(Object)} for when the argument is statically 19902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst * known to be another nonnull {@link Annotation}. Subclasses may wish to 20010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * override this with a hard-coded "&&" of field comparisons to improve 20110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * performance. 20210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 2033aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public boolean equals(Annotation o) { 20410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return def.equals(o.def()) 20502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst && fieldValues.equals(o.fieldValues); 20610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 20710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 20810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 20910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Returns the hash code of this annotation as defined on 21002ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst * {@link Annotation#hashCode}. Subclasses may wish to override 21110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * this with a hard-coded XOR/addition of fields to improve performance. 21210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 21310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 2143aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public int hashCode() { 21502ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst return def.hashCode() + fieldValues.hashCode(); 21610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 21710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 21810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 21910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Returns a string representation of this for 22010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * debugging purposes. For now, this method relies on 22110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link AbstractMap#toString} and the {@link Object#toString toString} 22210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * methods of the field values, so the representation is only a first 22310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * approximation to how the annotation would appear in source code. 22410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 22510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 2263aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public String toString() { 22710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali StringBuilder sb = new StringBuilder("@"); 22810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali sb.append(def.name); 22902ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst if (!fieldValues.isEmpty()) { 23010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali sb.append('('); 23102ac307c0d3fa53b83666972e0a75bc098500700Michael Ernst sb.append(fieldValues.toString()); 23210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali sb.append(')'); 23310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 23410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return sb.toString(); 23510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 23610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 23710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali} 23810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 23910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// package annotations; 24010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 24143367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernst// import org.checkerframework.checker.nullness.qual.Nullable; 242b69b006f7980741677c3acde6845363915695017Michael Ernst// 24310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// import annotations.el.*; 24410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// import annotations.util.coll.Keyer; 24510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 24610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 24710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * A top-level annotation containing an ordinary annotation plus a retention 24810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * policy. These are attached to {@link AElement}s. 24910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 2503aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst// public final class Annotation { 25110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public static final Keyer<String, Annotation> nameKeyer 25210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// = new Keyer<String, Annotation>() { 25310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public String getKeyFor( 2543aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst// Annotation v) { 25510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// return v.tldef.name; 25610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 25710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// }; 25810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 25910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 26010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * The annotation definition. 26110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 26210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public final AnnotationDef tldef; 26310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 26410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 26510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * The ordinary annotation, which contains the data and the ordinary 26610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * definition. 26710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 26810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public final Annotation ann; 26910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 27010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 27110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * Wraps the given annotation in a top-level annotation using the given 27210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * top-level annotation definition, which provides a retention policy. 27310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 27410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public Annotation(AnnotationDef tldef, Annotation ann) { 27510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// if (!ann.def().equals(tldef)) 27610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// throw new IllegalArgumentException("Definitions mismatch"); 27710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// this.tldef = tldef; 27810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// this.ann = ann; 27910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 28010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 28110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 28210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * Wraps the given annotation in a top-level annotation with the given 28310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * retention policy, generating the top-level annotation definition 28410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * automatically for convenience. 28510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 28610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public Annotation(Annotation ann1, 28710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// RetentionPolicy retention) { 28810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// this(new AnnotationDef(ann1.def(), retention), ann1); 28910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 29010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 29110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// /** 29210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// * {@inheritDoc} 29310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// */ 29410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// @Override 29510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public int hashCode() { 29610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// return tldef.hashCode() + ann.hashCode(); 29710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 29810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// 29910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// @Override 30010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// public String toString() { 30110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// StringBuilder sb = new StringBuilder(); 30210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// sb.append("tla: "); 30310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// sb.append(tldef.retention); 30410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// sb.append(":"); 30510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// sb.append(ann.toString()); 30610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// return sb.toString(); 30710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 30810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali// } 309