001package Torello.JavaDoc; 002 003 004// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 005// Standard-Java Imports 006// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 007 008import java.io.IOException; 009import java.util.Optional; 010import java.util.function.Consumer; 011 012 013// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 014// Java-HTML Imports 015// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 016 017import Torello.Java.*; 018 019import static Torello.Java.C.*; 020import static Torello.JavaDoc.PF.*; 021 022import Torello.Java.ReadOnly.ReadOnlyList; 023import Torello.Java.ReadOnly.ROArrayListBuilder; 024 025 026// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 027// The new Source-Code Parser: com.sun.source.* 028// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 029 030import com.sun.source.tree.MethodTree; 031import com.sun.source.tree.Tree; 032 033 034// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 035// JDUInternal 036// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 037 038import Torello.JDUInternal.Miscellaneous.EntityAnnotationData; 039 040 041/** 042 * <B CLASS=JDDescLabel>Reflection Class:</B> 043 * 044 * <BR />Holds all information extracted from <CODE>'.java'</CODE> Annotation 045 * (<CODE>@interface</CODE>) Source-Files about all Elements identified in that file. 046 * 047 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_GET_INST> 048 * <EMBED CLASS='external-html' DATA-FILE-ID=JPB_AELEM> 049 * <!-- EMBED CLASS='external-html' DATA-FILE-ID=JPB_AELEM_NOTE --> 050 */ 051@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID={"REFLECTION_EXTENSION"}) 052public class AnnotationElem 053 extends Declaration 054 implements java.io.Serializable, Comparable<AnnotationElem>, Cloneable 055{ 056 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 057 public static final long serialVersionUID = 1; 058 059 @Override 060 String codeHiLiteString() { return this.signature; } 061 062 063 // ******************************************************************************************** 064 // ******************************************************************************************** 065 // Public Fields: The Type, and the (optional) Default-Value 066 // ******************************************************************************************** 067 // ******************************************************************************************** 068 069 070 /** 071 * An Annotation-Element may only assume one of several types, as per the Java Sun / Oracle 072 * Documentation. The type must be one of the following, or a compile-time error occurs: 073 * 074 * <BR /><BR /><UL CLASS=JDUL> 075 * <LI>a primitive type</LI> 076 * <LI>String</LI> 077 * <LI>Class or an invocation of Class</LI> 078 * <LI>An enum type</LI> 079 * <LI>An annotation type</LI> 080 * <LI>An (1 dimensional) array type whose component type is one of the preceding types</LI> 081 * </UL> 082 */ 083 public final String type; 084 085 /** <EMBED CLASS='external-html' DATA-FILE-ID=JPB_JOW_2> */ 086 public final String typeJOW; 087 088 /** 089 * The default value assigned to this element. 090 * This may be null if there is no assigned default value. 091 */ 092 public final String defaultValue; 093 094 095 // ******************************************************************************************** 096 // ******************************************************************************************** 097 // AST Reference-Hook 098 // ******************************************************************************************** 099 // ******************************************************************************************** 100 101 102 /** 103 * <EMBED CLASS='external-html' DATA-FILE-ID=SSTB_HOOK_FIELD> 104 * 105 * If a user decides to make use of the native Oracle {@code MethodTree} instance that was 106 * used to build this {@code AnnotationElem} instance, it may be retrieved from this 107 * {@code transient} field. 108 * 109 * <BR /><BR /><B CLASS=JDDescLabel>{@code MethodTree} Note:</B> 110 * 111 * <BR />The package {@code com.sun.source.tree} "reuses" or "overloads" the {@code MethodTree} 112 * class. {@code com.sun.source.tree.MethodTree} can actually represent either a Method, or an 113 * Annotation-Element (or even a Constructor! but that's besides the point). 114 */ 115 public final transient MethodTree methodTree; 116 117 118 // ******************************************************************************************** 119 // ******************************************************************************************** 120 // Constructor - com.sun.source.tree 121 // ******************************************************************************************** 122 // ******************************************************************************************** 123 124 125 /** 126 * <EMBED CLASS="defs" DATA-KIND=AnnotationElem DATA-ENTITY=MethodTree> 127 * <EMBED CLASS='external-html' DATA-FILE-ID=RC_DESCRIPTION> 128 * @param mt <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_TREE> 129 * @param util <EMBED CLASS='external-html' DATA-FILE-ID=RC_PARAM_UTIL> 130 */ 131 public AnnotationElem( 132 final MethodTree mt, 133 final EntityAnnotationData ead, 134 final TreeUtils util 135 ) 136 { 137 super( 138 ead, // Stuff for building EntityAnnotationMirrors 139 util, // TreeUtils instance (contains all the parser and stuff) 140 mt, // 'Tree' instance 141 mt.getModifiers(), // ModifiersTree: Annotations on the Element & key-words 142 mt.getName().toString(), // Name Element 143 Entity.ANNOTATION_ELEM, // Entity 144 mt.getDefaultValue() // Treat the "default-value" as the "body" 145 ); 146 147 Tree defaultValue = mt.getDefaultValue(); 148 149 this.type = mt.getReturnType().toString(); 150 this.typeJOW = StrSource.typeToJavaIdentifier(this.type); 151 this.defaultValue = (defaultValue != null) ? defaultValue.toString().trim() : null; 152 153 // Reference Hook: This was built using the com.sun.source.tree.MethodTree class 154 this.methodTree = mt; 155 } 156 157 158 // ******************************************************************************************** 159 // ******************************************************************************************** 160 // Used Internally by 'SignatureParse' 161 // ******************************************************************************************** 162 // ******************************************************************************************** 163 164 165 // Ensures that the Version with longer type-information strings is used. Java Doc often uses 166 // longer type strings 167 168 public AnnotationElem(final AnnotationElem aeFromSourceParser, final String jdTypeStr) 169 { 170 super(aeFromSourceParser); 171 172 // 'AnnotationElem' specific fields. Copied from Google: 173 // 174 // Allowed member types (for Annotation-Members / Annotation-Elements) are the following: 175 // primitive types, String, Class, enumerated types, annotation types, and arrays of any 176 // of the above types (but not an array of arrays). 177 // 178 // This does mean that the "type" of an Annotation-Elem (sort-of) cannot be abbreviated or 179 // extended. There is no sense in explaining that 'String' is a 'java.lang.String' 180 181 this.type = jdTypeStr; 182 this.typeJOW = aeFromSourceParser.typeJOW; 183 this.defaultValue = aeFromSourceParser.defaultValue; 184 this.methodTree = aeFromSourceParser.methodTree; 185 } 186 187 188 // ******************************************************************************************** 189 // ******************************************************************************************** 190 // toString(...) 191 // ******************************************************************************************** 192 // ******************************************************************************************** 193 194 195 /** 196 * Generates a {@code String} of this {@code Annotation Element}, with all information included. 197 * @return A printable string of this {@code AnnotationElem}. 198 * @see #toString(int) 199 */ 200 public String toString() 201 { 202 String def = (defaultValue != null) 203 ? ("Default: [" + StrPrint.abbrevEndRDSF(defaultValue, MAX_STR_LEN, true) + 204 "]\n") 205 : ""; 206 207 return 208 "Name: [" + name + "]\n" + 209 "Declaration: [" + StrPrint.abbrevEndRDSF(signature, MAX_STR_LEN, true) + "]\n" + 210 "Type: [" + typeJOW + "]\n" + 211 "Modifiers: [" + StrCSV.toCSV(modifiers, true, true, null) + "]\n" + 212 def + 213 214 // This will **NEVER** be null - unless 'this' instance was built from an HTML File, 215 // rather than a source-code file. Instances like that are only used temporarily, and 216 // are garbage collected instantly. Do this check anyway (just in case). 217 218 "Location: " + ((this.location == null) 219 ? "null" 220 : ('[' + this.location.quickSummary() + ']')); 221 } 222 223 /** 224 * <EMBED CLASS='external-html' DATA-FILE-ID=TO_STR_PF> 225 * 226 * <BR /><BR />There is additional information printed by this {@code 'toString'} method 227 * (versus the zero-argument, standard, Java {@code 'toString'}). This method will print any 228 * available Java-Doc Comment's that were placed on this {@code AnnotationElem}. 229 * 230 * <BR /><BR />This {@code 'toString'} also allows for adding UNIX-Terminal color codes. 231 * 232 * @param flags These are defined in the {@link PF Print-Flags} class 233 * @return A printable {@code String} of this {@code AnnotationElem}. 234 * @see PF 235 * @see #toString() 236 */ 237 public String toString(int flags) 238 { 239 boolean color = (flags & UNIX_COLORS) > 0; 240 241 return 242 printedName("Element", 14, color) + 243 printedDeclaration(14, color) + 244 "Type-JOW: [" + typeJOW + "]\n" + 245 printedModifiers(14) + 246 printedLocation(14, color, (flags & BRIEF_LOCATION) > 0) + 247 248 // The previous method does not add a '\n' end to the end of the returned string 249 // These are both optional, they add a '\n' AT THE BEGINNING if one of them is included 250 251 printedDefault(color) + 252 printedComments(14, color, (flags & JAVADOC_COMMENTS) > 0); 253 } 254 255 private String printedDefault(boolean color) 256 { 257 // They need to abbreviate, seems extremely "unlikely" - but just in case... 258 return (defaultValue == null) 259 ? "" 260 : "\nDefault: [" + (color ? BGREEN : "") + 261 StrPrint.abbrevEndRDSF(defaultValue, MAX_STR_LEN, true) + 262 (color ? RESET : "") + "]"; 263 } 264 265 266 // ******************************************************************************************** 267 // ******************************************************************************************** 268 // CompareTo & Equals Stuff 269 // ******************************************************************************************** 270 // ******************************************************************************************** 271 272 273 /** 274 * Java's {@code interface Comparable<T>} requirements. This does a very simple comparison 275 * using the two elements' {@link #name} field. 276 * 277 * @param ae Any other {@code AnnotationElem} to be compared to {@code 'this' AnnotationElem} 278 * 279 * @return An integer that fulfills Java's {@code Comparable<AnnotationElem>} interface 280 * requirements. 281 */ 282 public int compareTo(AnnotationElem ae) 283 { return (this == ae) ? 0 : this.name.compareTo(ae.name); } 284 285 /** 286 * This <I>should be called an "atypical version" of </I> the usual {@code equals(Object 287 * other)} method. This version of equals merely compares the name of the element defined. 288 * The presumption here is that the definition of an 'element' only has meaning - <I>at all</I> 289 * - inside the context of an {@code Annotation} where that element has been defined. Since 290 * inside any {@code '.java'} {@code Annotation}, there may only be one element with a given 291 * name, this method shall return {@code TRUE} whenever the element being compared also has the 292 * same name. 293 * 294 * @param other This may be any other {@code Annotation-Element}. It is <I><B>strongly 295 * suggested</B></I> that {@code 'other'} be an {@code element} defined in the same 296 * {@code '.java'} source-code file as {@code 'this'} element. 297 * 298 * @return This method returns {@code TRUE} when {@code 'this'} instance of 299 * {@code AnnotationElem} has the same {@code 'name'} as the name of input-parameter 300 * {@code 'other'} 301 */ 302 public boolean equals(AnnotationElem other) 303 { return this.name.equals(other.name); } 304 305 306 // ******************************************************************************************** 307 // ******************************************************************************************** 308 // A.I. Token-Stream Generator-Method 309 // ******************************************************************************************** 310 // ******************************************************************************************** 311 312 313 public ReadOnlyList<ReadOnlyList<String>> getTokenStreams() 314 { 315 final ROArrayListBuilder<ReadOnlyList<String>> tokens = new ROArrayListBuilder<>(); 316 ROArrayListBuilder<String> b = new ROArrayListBuilder<>(); 317 318 tokens.add(ReadOnlyList.of("SECTION", "entity", "annotation-element")); 319 tokens.add(ReadOnlyList.of("SECTION", "name", this.name)); 320 tokens.add(ReadOnlyList.of("SECTION", "type", this.typeJOW)); 321 322 if ((this.defaultValue != null) && (!this.defaultValue.isEmpty())) 323 tokens.add(ReadOnlyList.of("SECTION", "default", this.defaultValue)); 324 325 if ((this.annotations != null) && (this.annotations.size() > 0)) 326 { 327 b.add("SECTION"); 328 b.add("annotations"); 329 for (String a : this.annotations) b.add(a); 330 tokens.add(b.build()); 331 } 332 333 return tokens.build(); 334 } 335 336}